总结如下:
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
具体如下图:
根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:
第一种方式:每个Bean都有一个代理
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context ="http://www.springframework.org/schema/context"
xmlns:aop ="http://www.springframework.org/schema/aop"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
< bean id ="sessionFactory"
class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="configLocation" value ="classpath:hibernate.cfg.xml" />
< property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration" />
</ bean >
<!-- 定义事务管理器(声明式的事务) -->
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
<!-- 配置DAO -->
< bean id ="userDaoTarget" class ="com.bluesky.spring.dao.UserDaoImpl" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< bean id ="userDao"
class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
<!-- 配置事务管理器 -->
< property name ="transactionManager" ref ="transactionManager" />
< property name ="target" ref ="userDaoTarget" />
< property name ="proxyInterfaces" value ="com.bluesky.spring.dao.GeneratorDao" />
<!-- 配置事务属性 -->
< property name ="transactionAttributes" >
< props >
< prop key ="*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
</ beans >
第二种方式:所有Bean共享一个代理基类
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context ="http://www.springframework.org/schema/context"
xmlns:aop ="http://www.springframework.org/schema/aop"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
< bean id ="sessionFactory"
class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="configLocation" value ="classpath:hibernate.cfg.xml" />
< property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration" />
</ bean >
<!-- 定义事务管理器(声明式的事务) -->
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< bean id ="transactionBase"
class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
lazy-init ="true" abstract ="true" >
<!-- 配置事务管理器 -->
< property name ="transactionManager" ref ="transactionManager" />
<!-- 配置事务属性 -->
< property name ="transactionAttributes" >
< props >
< prop key ="*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
<!-- 配置DAO -->
< bean id ="userDaoTarget" class ="com.bluesky.spring.dao.UserDaoImpl" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< bean id ="userDao" parent ="transactionBase" >
< property name ="target" ref ="userDaoTarget" />
</ bean >
</ beans >
第三种方式:使用拦截器
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context ="http://www.springframework.org/schema/context"
xmlns:aop ="http://www.springframework.org/schema/aop"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" >
< bean id ="sessionFactory"
class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="configLocation" value ="classpath:hibernate.cfg.xml" />
< property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration" />
</ bean >
<!-- 定义事务管理器(声明式的事务) -->
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< bean id ="transactionInterceptor"
class ="org.springframework.transaction.interceptor.TransactionInterceptor" >
< property name ="transactionManager" ref ="transactionManager" />
<!-- 配置事务属性 -->
< property name ="transactionAttributes" >
< props >
< prop key ="*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
< bean class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
< property name ="beanNames" >
< list >
< value > *Dao </ value >
</ list >
</ property >
< property name ="interceptorNames" >
< list >
< value > transactionInterceptor </ value >
</ list >
</ property >
</ bean >
<!-- 配置DAO -->
< bean id ="userDao" class ="com.bluesky.spring.dao.UserDaoImpl" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
</ beans >
第四种方式:使用tx标签配置的拦截器
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context ="http://www.springframework.org/schema/context"
xmlns:aop ="http://www.springframework.org/schema/aop"
xmlns:tx ="http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" >
< context:annotation-config />
< context:component-scan base-package ="com.bluesky" />
< bean id ="sessionFactory"
class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="configLocation" value ="classpath:hibernate.cfg.xml" />
< property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration" />
</ bean >
<!-- 定义事务管理器(声明式的事务) -->
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
< tx:advice id ="txAdvice" transaction-manager ="transactionManager" >
< tx:attributes >
< tx:method name ="*" propagation ="REQUIRED" />
</ tx:attributes >
</ tx:advice >
< aop:config >
< aop:pointcut id ="interceptorPointCuts"
expression ="execution(* com.bluesky.spring.dao.*.*(..))" />
< aop:advisor advice-ref ="txAdvice"
pointcut-ref ="interceptorPointCuts" />
</ aop:config >
</ beans >
第五种方式:全注解
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context ="http://www.springframework.org/schema/context"
xmlns:aop ="http://www.springframework.org/schema/aop"
xmlns:tx ="http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" >
< context:annotation-config />
< context:component-scan base-package ="com.bluesky" />
< tx:annotation-driven transaction-manager ="transactionManager" />
< bean id ="sessionFactory"
class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="configLocation" value ="classpath:hibernate.cfg.xml" />
< property name ="configurationClass" value ="org.hibernate.cfg.AnnotationConfiguration" />
</ bean >
<!-- 定义事务管理器(声明式的事务) -->
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" ref ="sessionFactory" />
</ bean >
</ beans >
此时在DAO上需加上@Transactional注解,如下:
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;
import com.bluesky.spring.domain.User;
@Transactional
@Component( " userDao " )
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
public List < User > listUsers() {
return this .getSession().createQuery( " from User " ).list();
}

}
注:1、一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。也就是说:最底层的方法如果设为@Transactional,那么所有调用它的方法必须也是@Transactional,否则事务不会起作用。
2、默认情况下,@Transactional 方法中,在抛出unchecked异常时,数据库会回滚;在抛出checked异常时,数据库不会回滚。当然也可以特别引起指定数据库回滚的异常,如:
@Transactional(rollBackFor=Exception.class) : method1对于Exception类的异常都会回滚
public void method1(){
......
}
@Transactional(propagation=Propagation.NOT_SUPPORTED) :method2取消了事务控制
public void method2(){
.....
}
3、 在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。
4、@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
5.、注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。
6、 通过 元素的 " proxy-target-class" 属性值来控制是基于接口的还是基于类的代理被创建。如果 "proxy-target-class" 属值被设置为 "true",那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 "proxy-target-class" 属值被设置为 "false" 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。
标准的JDK基于接口的代理将起作用
proxy-target-class="false"/>
基于类的代理将起作用 ,同时 cglib.jar必须在CLASSPATH中
proxy-target-class="true"/>
非JTA事务(即非分布式事务), 事务配置的时候 ,需要指定dataSource属性(非分布式事务,事务是在数据库创建的链接上开启。)
JTA事务(非分布式事务), 事务配置的时候 ,不能指定dataSource属性(分布式事务,是有全局事务来管理数据库链接的)
7、注解@Transactional cglib与java动态代理最大区别是代理目标对象不用实现接口,那么注解要是写到接口方法上,要是使用cglib代理,这是注解事物就失效了,为了保持兼容注解最好都写到实现类方法上。
8、 Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。
5万+

被折叠的 条评论
为什么被折叠?



