spring与hibernate整合之声明式事务管理

声明式事务配置
* 配置SessionFactory
* 配置事务管理器
* 事务的传播特性
* 那些类那些方法使用事务

  • 配置内容:

1)装配数据源和工厂

[html]  view plain copy
  1. <bean id="dataSource"  
  2.         class="org.apache.commons.dbcp.BasicDataSource">  
  3.         <property name="driverClassName"  
  4.             value="com.mysql.jdbc.Driver">  
  5.         </property>  
  6.         <property name="url" value="jdbc:mysql://localhost/newsdb?characterEncoding=utf8"></property>  
  7.         <property name="username" value="root"></property>  
  8.         <property name="password" value="123456"></property>  
  9.     </bean>  
  10.     <bean id="sessionFactory"  
  11.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  12.         <property name="dataSource">  
  13.             <ref bean="dataSource" />  
  14.         </property>  
  15.         <property name="hibernateProperties">  
  16.             <props>  
  17.                 <prop key="hibernate.dialect">  
  18.                     org.hibernate.dialect.MySQLDialect  
  19.                 </prop>  
  20.                 <prop key="show_sql">true</prop>  
  21.             </props>  
  22.         </property>  
  23.         <property name="mappingResources">  
  24.             <list>  
  25.                 <value>mapping.xml</value>  
  26.             </list>  
  27.         </property>  
  28.     </bean>  
2)装配事务管理

<!-- 配置事务管理器 -->

[html]  view plain copy
  1. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  2.    <property name="sessionFactory">  
  3.        <ref bean="sessionFactory"/>  
  4.    </property>  
  5. </bean>  
3)装配事务属性

[html]  view plain copy
  1. <!--  配置事务传播特性 -->  
  2. <tx:advice id="TestAdvice" transaction-manager="transactionManager">  
  3.     <tx:attributes>  
  4.       <tx:method name="add*" propagation="REQUIRED"/>  
  5.       <tx:method name="del*" propagation="REQUIRED"/>  
  6.       <tx:method name="update*" propagation="REQUIRED"/>  
  7.       <tx:method name="add*" propagation="REQUIRED"/>  
  8.       <tx:method name="find*" propagation="REQUIRED"/>  
  9.       <tx:method name="get*" propagation="REQUIRED"/>  
  10.       <tx:method name="apply*" propagation="REQUIRED"/>  
  11.     </tx:attributes>  
  12. </tx:advice>  

4)确定切面,需要使用事务的bean

[html]  view plain copy
  1. <!--  配置参与事务的类 -->  
  2. <aop:config>  
  3. <aop:pointcut id="allTestServiceMethod" expression="execution(* manager.*.*(..))"/>  
  4. <aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice" />  
  5. </aop:config>  
5)常规bean可以配到另外的装配文件中

[html]  view plain copy
  1. <bean id="bookManager" class="manager.BookManager" >  
  2.         <property name="hibernateTemplate">  
  3.             <ref bean="hibernateTemplate" />  
  4.         </property>  
  5. </bean>  
如果bean中不使用hibernateTemplate,可以不注入此对象
[html]  view plain copy
  1. <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate" >  
  2.     <property name="sessionFactory">  
  3.         <ref local="sessionFactory" />  
  4.     </property>  
  5. </bean>                                                              

  • @Transactional实现事务管理

对声明式事务管理,Spring提供基于@Transactional注解方式来实现,但需要Java 5+。

 

注解方式是最简单的事务配置方式,可以直接在Java源代码中声明事务属性,且对于每一个业务类或方法如果需要事务都必须使用此注解。

      

接下来学习一下注解事务的使用吧: 

1、定义业务逻辑实现:

 

java代码:
查看复制到剪贴板打印
  1. package cn.javass.spring.chapter9.service.impl;  
  2. //省略import  
  3. public class AnnotationUserServiceImpl implements IUserService {  
  4.     private IUserDao userDao;  
  5.     private IAddressService addressService;  
  6.     public void setUserDao(IUserDao userDao) {  
  7.         this.userDao = userDao;  
  8.     }  
  9.     public void setAddressService(IAddressService addressService) {  
  10.         this.addressService = addressService;  
  11.     }  
  12.     @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED)  
  13.     @Override  
  14.     public void save(final UserModel user) {  
  15.         userDao.save(user);  
  16.         user.getAddress().setUserId(user.getId());  
  17.         addressService.save(user.getAddress());  
  18.     }  
  19.     @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=true)  
  20.     @Override  
  21.     public int countAll() {  
  22.         return userDao.countAll();  
  23.     }  
  24. }  

 

2.3、事务相关配置:

 

java代码:
查看复制到剪贴板打印
  1. <tx:annotation-driven transaction-manager="txManager"/>   

使用如上配置已支持声明式事务。

  •  @Transactional配置详解

Spring提供的<tx:annotation-driven/>用于开启对注解事务管理的支持,从而能识别Bean类上的@Transactional注解元数据,其具有以下属性:

  • transaction-manager:指定事务管理器名字,默认为transactionManager,当使用其他名字时需要明确指定;
  • proxy-target-class:表示将使用的代码机制,默认false表示使用JDK代理,如果为true将使用CGLIB代理
  • order:定义事务通知顺序,默认Ordered.LOWEST_PRECEDENCE,表示将顺序决定权交给AOP来处理。

Spring使用@Transaction来指定事务属性,可以在接口、类或方法上指定,如果类和方法上都指定了@Transaction,则方法上的事务属性被优先使用,具体属性如下:

  • value:指定事务管理器名字,默认使用<tx:annotation-driven/>指定的事务管理器,用于支持多事务管理器环境;
  • propagation:指定事务传播行为,默认为Required,使用Propagation.REQUIRED指定;
  • isolation:指定事务隔离级别,默认为“DEFAULT”,使用Isolation.DEFAULT指定;
  • readOnly:指定事务是否只读,默认false表示事务非只读;
  • timeout:指定事务超时时间,以秒为单位,默认-1表示事务超时将依赖于底层事务系统;
  • rollbackFor:指定一组异常类,遇到该类异常将回滚事务;
  • rollbackForClassname:指定一组异常类名字,其含义与<tx:method>中的rollback-for属性语义完全一样;
  • noRollbackFor:指定一组异常类,即使遇到该类异常也将提交事务,即不回滚事务;
  • noRollbackForClassname:指定一组异常类名字,其含义与<tx:method>中的no-rollback-for属性语义完全一样;

 

Spring提供的@Transaction注解事务管理内部同样利用环绕通知TransactionInterceptor实现事务的开启及关闭。

使用@Transaction注解事务管理需要特别注意以下几点:

  • 如果在接口、实现类或方法上都指定了@Transactional 注解,则优先级顺序为方法>实现类>接口;
  • 建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制是没问题,因为其使用基于接口的代理;而使用使用CGLIB代理机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”
  • 在JDK代理机制下,“自我调用”同样不会应用相应的事务属性,其语义和<tx:tags>中一样;
  • 默认只对RuntimeException异常回滚;
  • 在使用Spring代理时,默认只有在public可见度的方法的@Transactional 注解才是有效的,其它可见度(protected、private、包可见)的方法上即使有@Transactional 注解也不会应用这些事务属性的,Spring也不会报错,如果你非要使用非公共方法注解事务管理的话,可考虑使用AspectJ。


2、编写业务逻辑方法
* 继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate是
  Hibernate Session的轻量级封装
* 默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的
* 编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理
* 关于事务边界的设置,通常设置到业务层,不要添加到Dao上  

3、了解事务的几种传播特性
1.PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启。这是最常见的选择,没特殊性需求,这个足矣
2.PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3.PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4.PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5.PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
6.PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
7.PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 
     则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

4、Spring事务的隔离级别
1.ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
     另外四个与JDBC的隔离级别相对应
2.ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
     这种隔离级别会产生脏读,不可重复读和幻像读。
3.ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4.ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
     它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5.ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
     除了防止脏读,不可重复读外,还避免了幻像读。

你可能感兴趣的:(spring,Hibernate)