Spring事物笔记
/**什么异常时才回滚**/
Spring事务策略
由PlatformTransactionManager接口定义:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
getTransaction(..)方法根据一个类型为 TransactionDefinition 的参数返回一个 TransactionStatus 对象。返回的 TransactionStatus 对象可能代表一个新的或已经存在的事务。
TransactionDefinition接口指定:
事务隔离:当前事务和其它事务的隔离的程度。例如,这个事务能否看到其他事务未提交的写数据?
事务传播:通常在一个事务中执行的所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在,有几个选项可以指定一个事务性方法的执行行为:例 如,简单地在现有的事务中继续运行(大多数情况);或者挂起现有事务,创建一个新的事务。Spring提供EJB CMT中常见的事务传播选项。
事务超时: 事务在超时前能运行多久(自动被底层的事务基础设施回滚)。
只读状态: 只读事务不修改任何数据。只读事务在某些情况下(例如当使用Hibernate时),是一种非常有用的优化。
在TransactionDefinition接口中定义了五个不同的事务隔离级别
ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED? 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
ISOLATION_REPEATABLE_READ? 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
事物传播
PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
TransactionStatus 接口
为处理事务的代码提供一个简单的控制事务执行和查询事务状态的方法。
public interface TransactionStatus {
boolean isNewTransaction();
void setRollbackOnly();
boolean isRollbackOnly();
}
PlatformTransactionManager以TransactionStatus处理事务,TransactionStatus 这个接口有三个方法
isNewTransaction() ,isRollbackOnly(),setRollbackOnly()。PlatformTransactionManager就是根据前两个方法决 定是否要创建一个新事务,是要递交还是回滚。总结上面所说的,spring的事务由PlatformTransactionManager管 理,manager最后调用事务源的方法来实现一个事务过程。而manager通过TransactionStatus 来决定如何实现。
声明式事务管理:
在理解Spring的声明式事务管理方面最重要的概念是:Spring的事务管理是通过AOP代理实现的。代理对象与事务元数据结合产生了一个AOP代 理,它使用一个PlatformTransactionManager 实现品配合TransactionInterceptor,在方法调用前后实施事务。
……
<bean id="fooService" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
</aop:config>
……
'transaction-manager' 属性被设置为一个指向 PlatformTransactionManager bean的名字(这里指 'txManager'), 该bean将会真正管理事务。事实上,如果 PlatformTransactionManager bean的名字是 'transactionManager' 的话,你的事务通知(<tx:advice/>)中的 'transaction-manager' 属性可以忽略。否则你则需要像上例那样明确指定。
声明式配置控制事务的回滚:
Spring框架的事务基础架构代码将默认地只在抛出运行时和unchecked exceptions时才标识事务回滚。也就是说,当抛出一个 RuntimeException或其子类例的实例时。从事务方法中抛出的Checked exceptions将不被标识进行事务回滚。
可以配置哪些 Exception类型将被标识进行事务回滚。
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
不想在异常抛出的时候回滚事务,就可以使用“不回滚规则”。
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
编程式 方式来指定回滚事务
public void resolvePosition() {
try {
// some business logic...
} catch (NoProductInStockException ex) {
// trigger rollback programmatically
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
<tx:advice/> 有关的设置:
事务传播设置 是 属性是否需要?默认值描述
默认的 <property name="timeout" value="30"/>
</bean>"
使用PlatformTransactionManager
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
// execute your business logic here
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);
参考:
http://www.javaeye.com/topic/11190
http://www.javaeye.com/topic/199813
http://www.javaeye.com/topic/78674
http://www.javaeye.com/topic/35907
http://hi.baidu.com/brnz/blog/item/85c78b39831086e414cecb77.html