zoukankan      html  css  js  c++  java
  • Spring整合Hibernate:2、使用Annotation方式进行声明式的事务管理

    1、加入DataSourceTransactionManager的命名空间

    修改applicationContext.xml文件,增加如下内容:


    2、初始化HibernateTransactionManager

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <?xml version="1.0" encoding="UTF-8"?>
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        <context:annotation-config />
        <context:component-scan base-package="com.fz.annotation" />
        <bean
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations" value="classpath:jdbc.properties" />
        </bean>
        <bean id="dataSource" destroy-method="close"
            class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
        <!-- annotation方式管理hibernate的sessionFactory -->
        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan">
                <list>
                    <value>com.fz.annotation.model</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.format_sql">true</prop>
                </props>
            </property>
        </bean>
        <tx:annotation-driven transaction-manager="myTxManager"/>
        <bean id="myTxManager"
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
    </beans>

    这里需要配置一个HibernateTransactionManager的bean和<tx:annotation-driven transaction-manager="myTxManager"/>

    3、在Service层使用事务管理

    userServiceImpl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    package com.fz.annotation.service.impl;
     
    import javax.annotation.Resource;
     
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
     
    import com.fz.annotation.dao.UserDao;
    import com.fz.annotation.model.User;
    import com.fz.annotation.service.UserService;
     
    @Service("userService")
    public class UserServiceImpl implements UserService{
        private UserDao userDao;
         
        @Transactional
        public void userAdd(User user) {
            userDao.userAdd(user);
        }
         
        public UserDao getUserDao() {
            return userDao;
        }
        @Resource(name="userDao")
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
         
    }

    注意:这里使用@Transactional注解来注明该方法需要使用到事务

    userDaoImpl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.fz.annotation.dao.impl;
     
    import javax.annotation.Resource;
     
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.stereotype.Repository;
     
    import com.fz.annotation.dao.UserDao;
    import com.fz.annotation.model.User;
     
     
    @Repository("userDao")
    public class UserDaoImpl implements UserDao{
        private SessionFactory sessionFactory;
        public void userAdd(User user) {
            Session session = sessionFactory.getCurrentSession();
            session.save(user);
        }
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }
        @Resource
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    }

    4、测试

    测试正常情况,结果一切正常。数据库也插入了数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Test
    public void getProperties(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext_aop.xml");
        UserService userService = (UserService) ctx.getBean("userService");
        User user = new User();
        user.setId(4);
        user.setUsername("test1");
        userService.userAdd(user);
    }

    修改userDaoImpl.java,抛出一个异常。看看是否能回滚

    在userDaoImpl.java的userAdd方法中抛出一个异常

    1
    2
    3
    4
    5
    public void userAdd(User user) {
        Session session = sessionFactory.getCurrentSession();
        session.save(user);
        throw new RuntimeException("aa");
    }

    然后再次测试的时候,发现数据库中没有插入该条数据。依然是上一次的数据

    5、事务的传播特性Propagation

    所谓传播特性:也就是Transaction的产生过程,以及事务来了后怎么管理这个事务。

    @Transactional注解有个属性:Propagation,Propagation是一个枚举类型,默认是REQUIRED,枚举值如下:

    REQUIRED(默认,最常用,重要)

              Support a current transaction, create a new one if none exists. 

    如果此时执行了mothod1,而method1里面又调用了method2.假如method1里面已经有了Transaction,那么method2里面就不需要再创建新的Transaction了,method2会使用原来的这个Transaction。如果method1里面没有Transaction,则method2会新建一个Transaction

    例如:

    1
    2
    3
    4
    @Transactional(propagation=Propagation.REQUIRED)
    public void userAdd(User user) {
        userDao.userAdd(user);
    }

    如果别的service调用userAdd的时候已经有了Transaction,则此时不会创建新的Transaction。如果调用的时候没有Transaction。则这里会新建一个Transaction

    MANDATORY 

              Support a current transaction, throw an exception if none exists.

              必须得有Transaction,没有则抛异常。

    例如:如果把上面的REQUIRED改为MANDATORY,如果调用这个userAdd方法之前必须得有Transaction存在。否则则抛异常。

    1
    2
    3
    4
    @Transactional(propagation=Propagation.MANDATORY)
    public void userAdd(User user) {
        userDao.userAdd(user);
    }


    NESTED 

              Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.

              如果有一个Transaction(A)存在了,则暂停A。自己新建一个Transaction(B),等B执行完了,A才会继续执行。就是新建一个Transaction内嵌到原来的Transaction中。

    NEVER 

              Execute non-transactionally, throw an exception if a transaction exists.

              必须没有Transaction,如果有Transaction则抛异常。

    NOT_SUPPORTED 

              Execute non-transactionally, suspend the current transaction if one exists.

              必须不能有Transaction,如果有则挂起原来的Transaction,暂停原来的Transaction,执行当前方法内的Transaction后,原来的Transaction再继续。

    REQUIRES_NEW 

              Create a new transaction, suspend the current transaction if one exists.

              创建一个新Transaction,如果当前有Transaction。就将其挂起(暂停)

    SUPPORTS 

              Support a current transaction, execute non-transactionally if none exists.

              支持当前Transaction,如果当前有则有,当前没有则没有。












  • 相关阅读:
    JavaScript对原始数据类型的拆装箱操作
    Javascript继承(原始写法,非es6 class)
    动态作用域与词法作用域
    自行车的保养
    探索JS引擎工作原理 (转)
    C语言提高 (7) 第七天 回调函数 预处理函数DEBUG 动态链接库
    C语言提高 (6) 第六天 文件(续) 链表的操作
    C语言提高 (5) 第五天 结构体,结构体对齐 文件
    C语言提高 (4) 第四天 数组与数组作为参数时的数组指针
    C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间
  • 原文地址:https://www.cnblogs.com/meet/p/4762389.html
Copyright © 2011-2022 走看看