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,如果当前有则有,当前没有则没有。












  • 相关阅读:
    8天学通MongoDB——第三天 细说高级操作
    8天学通MongoDB——第二天 细说增删查改
    8天学通MongoDB——第一天 基础入门
    Redis Web界面管理工具
    Redis 起步
    使用 Swagger UI 与 Swashbuckle 创建 RESTful Web API 帮助文件
    面试应该如何面?
    Login oracle for external authenticate
    突然发现我脾气变好了
    一种持续构建构想
  • 原文地址:https://www.cnblogs.com/meet/p/4762389.html
Copyright © 2011-2022 走看看