• Spring整合hibernate4:事务管理


     Spring整合hibernate4:事务管理

    Spring和Hibernate整合后,通过Hibernate API进行数据库操作时发现每次都要opensession,close,beginTransaction,commit,这些都是重复的工作,我们可以把事务管理部分交给spring框架完成。

    配置事务(xml方式)

    使用spring管理事务后在dao中不再需要调用beginTransaction和commit,也不需要调用session.close(),使用API  sessionFactory.getCurrentSession()来替代sessionFactory.openSession()

     1 @Repository
     2 public class UserDaoImpl implements UserDao {
     3     @Autowired
     4     private SessionFactory sessionFactory;
     5     
     6     public User findUserById(int id) {
     7         Session session = sessionFactory.getCurrentSession();
     8         User user = (User)session.get(User.class, id);
     9         session.delete(user);
    10         
    11         return user;
    12     }
    13 }

    采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()创建的session则不会。

    采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()创建的session必须手动关闭。

    使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:

    * 如果使用的是本地事务(jdbc事务)

    <property name="hibernate.current_session_context_class">thread</property>

    * 如果使用的是全局事务(jta事务)

    <property name="hibernate.current_session_context_class">jta</property>

    如果采用的时Hibernate4,使用getCurrentSession()必须配置事务,否则无法取到session

    applicationContext.xml配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans
     3     xmlns="http://www.springframework.org/schema/beans"
     4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     5     xmlns:p="http://www.springframework.org/schema/p"
     6     xmlns:context="http://www.springframework.org/schema/context"
     7     xmlns:aop="http://www.springframework.org/schema/aop"
     8     xmlns:tx="http://www.springframework.org/schema/tx"
     9     xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    10     xmlns:cache="http://www.springframework.org/schema/cache"
    11     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    12                         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    13                         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    14                         http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    15                         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    16                         http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    17     
    18     <context:component-scan base-package="dao"/>
    19     <context:component-scan base-package="service"/>
    20     <context:component-scan base-package="test"/>
    21     
    22     <context:property-placeholder location="classpath:dbcp.properties"/>
    23     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    24         <property name="driverClassName" value="${driverClassName}" />
    25         <property name="url" value="${url}" />
    26         <property name="username" value="${mysqlusername}" />
    27         <property name="password" value="${mysqlpassword}" />
    28         <property name="maxActive" value="${maxActive}" />
    29         <property name="maxIdle" value="${maxIdle}" />
    30         <property name="minIdle" value="${minIdle}" />
    31         <property name="maxWait" value="${maxWait}" />
    32         <property name="initialSize" value="${initialSize}" />
    33         <property name="logAbandoned" value="${logAbandoned}" />
    34         <property name="removeAbandoned" value="${removeAbandoned}" />
    35         <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
    36         <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
    37         <property name="numTestsPerEvictionRun" value="${numTestsPerEvictionRun}" />
    38     </bean>
    39     
    40     <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    41         <property name="dataSource" ref="dataSource" />
    42         
    43         <property name="hibernateProperties">
    44             <props>
    45                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    46                 <prop key="hibernate.show_sql">true</prop>
    47                 <prop key="current_session_context_class">thread</prop>
    48             </props>
    49         </property>
    50         
    51         <property name="packagesToScan">
    52             <list>
    53                 <value>po</value>
    54             </list>
    55         </property>
    56     </bean>
    57 
    58     
    59     <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到--> 
    60     <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    61         <property name="sessionFactory" ref="sessionFactory"></property>  
    62     </bean>
    63     
    64     <tx:advice id="txAdvice" transaction-manager="txManager">
    65         <tx:attributes>
    66             <tx:method name="find*" propagation="REQUIRED" />
    67             <tx:method name="*" read-only="true"/>
    68         </tx:attributes>
    69     </tx:advice>
    70     
    71     <aop:config proxy-target-class="true">
    72         <!-- <aop:advisor advice-ref="txAdvice" pointcut="execution(* dao.*.*(..))"/> -->
    73         <aop:pointcut expression="execution(* dao.*.*(..))" id="pointcut"/>
    74         <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    75     </aop:config>
    76 
    77 </beans>

    Spring中Propagation类的事务属性详解:

    PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 

    PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。 

    PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。 

    PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

    PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 

    PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。 

    PROPAGATION_NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

    配置事务(声明方式)

    需要在xml配制中设置<tx:annotation-driven transaction-manager="transactionManager"

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans
     3     xmlns="http://www.springframework.org/schema/beans"
     4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     5     xmlns:p="http://www.springframework.org/schema/p"
     6     xmlns:context="http://www.springframework.org/schema/context"
     7     xmlns:aop="http://www.springframework.org/schema/aop"
     8     xmlns:tx="http://www.springframework.org/schema/tx"
     9     xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    10     xmlns:cache="http://www.springframework.org/schema/cache"
    11     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    12                         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    13                         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    14                         http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    15                         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    16                         http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    17     
    18     <context:component-scan base-package="dao"/>
    19     <context:component-scan base-package="service"/>
    20     <context:component-scan base-package="test"/>
    21     
    22     <context:property-placeholder location="classpath:dbcp.properties"/>
    23     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    24         <property name="driverClassName" value="${driverClassName}" />
    25         <property name="url" value="${url}" />
    26         <property name="username" value="${mysqlusername}" />
    27         <property name="password" value="${mysqlpassword}" />
    28         <property name="maxActive" value="${maxActive}" />
    29         <property name="maxIdle" value="${maxIdle}" />
    30         <property name="minIdle" value="${minIdle}" />
    31         <property name="maxWait" value="${maxWait}" />
    32         <property name="initialSize" value="${initialSize}" />
    33         <property name="logAbandoned" value="${logAbandoned}" />
    34         <property name="removeAbandoned" value="${removeAbandoned}" />
    35         <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
    36         <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
    37         <property name="numTestsPerEvictionRun" value="${numTestsPerEvictionRun}" />
    38     </bean>
    39     
    40     <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    41         <property name="dataSource" ref="dataSource" />
    42         
    43         <property name="hibernateProperties">
    44             <props>
    45                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    46                 <prop key="hibernate.show_sql">true</prop>
    47                 <prop key="current_session_context_class">thread</prop>
    48             </props>
    49         </property>
    50         
    51         <property name="packagesToScan">
    52             <list>
    53                 <value>po</value>
    54             </list>
    55         </property>
    56     </bean>
    57 
    58     
    59     <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    60         <property name="sessionFactory" ref="sessionFactory"></property>  
    61     </bean>
    62     <tx:annotation-driven transaction-manager="txManager"/>
    63     
    64 </beans>

    事物注解方式: @Transactional

    当标于类前时,标示类中所有方法都进行事物处理,以下代码在service层进行事务处理(给Service层配置事务是比较好的方式,因为一个 Service层方法操作可以关联到多个DAO的操作。在Service层执行这些Dao操作,多DAO操作有失败全部回滚,成功则全部提交。)

     1 @Service
     2 @Transactional
     3 public class UserServiceImpl implements UserService {
     4     @Autowired
     5     private UserDao userDao;
     6     
     7     public User getUserById(int id) {
     8         return userDao.findUserById(id);
     9     }
    10 }

    当类中某些方法不需要事物时:

     1 @Service
     2 @Transactional
     3 public class UserServiceImpl implements UserService {
     4     @Autowired
     5     private UserDao userDao;
     6     
     7     @Transactional(propagation = Propagation.NOT_SUPPORTED)
     8     public User getUserById(int id) {
     9         return userDao.findUserById(id);
    10     }
    11 }

    @Transactional(propagation=Propagation.REQUIRED) 

    如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
    @Transactional(propagation=Propagation.NOT_SUPPORTED) 
    容器不为这个方法开启事务
    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
    @Transactional(propagation=Propagation.MANDATORY) 
    必须在一个已有的事务中执行,否则抛出异常
    @Transactional(propagation=Propagation.NEVER) 
    必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
    @Transactional(propagation=Propagation.SUPPORTS) 
    如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

    事物超时设置:
    @Transactional(timeout=30) //默认是30秒

    事务隔离级别:
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    读取未提交数据(会出现脏读, 不可重复读) 基本不使用
    @Transactional(isolation = Isolation.READ_COMMITTED)
    读取已提交数据(会出现不可重复读和幻读)
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    可重复读(会出现幻读)
    @Transactional(isolation = Isolation.SERIALIZABLE)
    串行化

    MYSQL: 默认为REPEATABLE_READ级别
    SQLSERVER: 默认为READ_COMMITTED

    脏读 : 一个事务读取到另一事务未提交的更新数据
    不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 
    后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
    读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
    幻读 : 一个事务读到另一个事务已提交的insert数据

  • 相关阅读:
    MySQL5.7二进制安装及多实例
    MySQL5.7版本的yum安装方式
    PHP安装
    MySQL5.6安装部署及多实例主从
    Prometheus监控MySQL和Linux主机结合Grafana出图
    MySQL5.7源码安装(编译)
    MySQL基本管理
    WC框架
    .NET 调用虚方法2 转
    .NET 调用虚方法1 转
  • 原文地址:https://www.cnblogs.com/1995hxt/p/4944918.html
Copyright © 2020-2023  润新知