spring 事务详解
来源:程序员人生 发布时间:2016-12-15 10:11:22 阅读次数:4298次
1、甚么是事务
事务是1系列的动作,它们综合在1起才是1个完全的工作单元,这些动作必须全部完成,如果有1个失败的话,那末事务就会回滚到最开始的状态。事务有4个特性ACID:
- 原子性(Atomicity):事务是1个原子操作,由1系列动作组成。事务的原子性确保动作要末全部完成,要末完全不起作用。
- 1致性(Consistency):1旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于1致的状态,而不会是部份完成部份失败
- 隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每一个事务都应当与其他事务隔离开来,避免数据破坏。
- 持久性(Durability):1旦事务完成,不管产生甚么系统毛病,它的结果都不应当遭到影响。通常情况下,事务的结果被写到持久化存储器中。
2、spring事务管理器
Spring其实不直接收理事务,而是提供了多种事务管理器。Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。接口中有3个方法
public interface PlatformTransactionManager {
//根据事务定义TransactionDefinition,获得事务
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
//提交事务
void commit(TransactionStatus status) throws TransactionException;
//回滚事务
void rollback(TransactionStatus status) throws TransactionException;
}
其中,TransactionDefinition是事务的1些基础信息,如超时时间,隔离级别,传播特性等;TransactionStatus是事务的状态,如是否是1个新事务,是不是被标记为回滚等。Spring针对不同的ORM提供的事务管理器,都是集成自AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager又实现了PlatformTransactionManager。
2.1 JDBC、Mybatis和ibatis事务管理器
如果利用程序中直接使用JDBC来进行持久化,需要配置JDBC事务管理器DataSourceTransactionManager,通过DataSource获得到java.sql.Connection来管理事务,调用连接的commit()方法来提交事务,一样,事务失败则通过调用rollback()方法进行回滚。
-
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
2.2 Hibernate事务管理器 -
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
2.3 JPA事务管理器 -
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
通过entityManagerFactory属性指定需要事务管理的javax.persistence.EntityManagerFactory对象。还需要为entityManagerFactory对象指定jpaDialect属性,该属性所对应的对象指定了如何获得连接对象、开启事务、关闭事务等事务管理相干的行动。
-
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
……
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
2.4 Java散布式事务管理器JTA -
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="jotm" />
</bean>
-
<!-- JOTM实例 -->
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean">
<property name="defaultTimeout" value="500000"/>
</bean>
散布式事务通常是指多个数据源之间的实物,在tomcat下,是没有散布式事务的,不过可以借助于第3方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现。
2.5 JDO事务管理器
-
<bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager">
<property name="persistenceManagerFactory" ref="persistenceManagerFactory"/>
</bean>
通过persistenceManagerFactory属性指定需要事务管理的javax.jdo.PersistenceManagerFactory对象。
具体可参考:http://hhhk.iteye.com/blog/2082714
3、Spring事务的特性
1、事务的传播行动
所谓事务的传播行动是指,如果在开始当前事务之前,1个事务上下文已存在,此时有若干选项可以指定1个事务性方法的履行行动。在TransactionDefinition定义中包括了以下几个表示传播行动的常量:
-
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建1个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建1个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建1个新的事务。这是默许值。
2、事务的隔离级别
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了5个表示隔离级别的常量:
-
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示1个事务可以读取另外一个事务修改但还没有提交的数据。该级别不能避免脏读,不可重复读和幻读,因此很少使用该隔离级别。
TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示1个事务只能读取另外一个事务已提交的数据。该级别可以避免脏读,这也是大多数情况下的推荐值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示1个事务在全部进程中可以屡次重复履行某个查询,并且每次返回的记录都相同。该级别可以避免脏读和不可重复读。
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务顺次逐一履行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以避免脏读、不可重复读和幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
3、只读属性
事务的第3个特性是它是不是为只读事务。如果事务只对后真个数据库进行该操作,数据库可以利用事务的只读特性来进行1些特定的优化。
4、事务超时
由于事务可能触及对后端数据库的锁定,所以长时间的事务会没必要要的占用数据库资源。事务超时就是事务的1个定时器,在特定时间内事务如果没有履行终了,那末就会自动回滚,而不是1直等待其结束。
5、回滚规则
唆使spring事务管理器回滚1个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后根据规则决定是不是回滚抛出异常的事务。默许配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会致使事务回滚),而抛出checked异常则不会致使事务回滚。可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也能够明肯定义那些异常抛出时不回滚事务。还可以编程性的通过setRollbackOnly()方法来唆使1个事务必须回滚,在调用完setRollbackOnly()后你所能履行的唯1操作就是回滚。
6、事务状态
public interface TransactionStatus{
boolean isNewTransaction(); // 是不是是新的事物
boolean hasSavepoint(); // 是不是有恢复点
void setRollbackOnly(); // 设置为只回滚
boolean isRollbackOnly(); // 是不是为只回滚
boolean isCompleted; // 是不是已完成
}
4、Spring支持的事务管理
Spring提供了对编程式事务和声明式事务的支持,编程式事务允许用户在代码中精肯定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。
Spring配置文件中关于事务配置总是由3个组成部份,分别是DataSource、TransactionManager和代理机制这3部份,不管哪一种配置方式,1般变化的只是代理机制这部份。DataSource、TransactionManager这两部份只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
1、编程式事务
Spring提供两种方式的编程式事务管理,分别是:使用TransactionTemplate和直接使用PlatformTransactionManager。
1)采取TransactionTemplate和采取其他Spring模板,如JdbcTempalte和HibernateTemplate是1样的方法,它使用回调方法,把利用程序从处理获得和释放资源中摆脱出来。TransactionTemplate是线程安全的。
-
<!-- JDBC事务管理器 注意:事务管理器传的参数是数据源-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager" scope="singleton">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 声明事务模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
</bean>
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
// Transactional code threw error -> rollback
rollbackOnException(status, err);
throw err;
}
catch (Exception ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
可以看到transactionTemplate 的履行是在execute中的,所以 -
TransactionTemplate tt = new TransactionTemplate(); // 新建1个TransactionTemplate
Object result = tt.execute(
new TransactionCallback(){
public Object doTransaction(TransactionStatus status){
updateOperation();
return resultOfUpdateOperation();
}
}); // 履行execute方法进行事务管理
2)使用PlatformTransactionManager
2、声明式事务管理
1)利用aop配置
-
<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>
2)声明式注解事务 -
<!-- 注解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager" />
3)使用拦截器 -
<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>
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠