??xml version="1.0" encoding="utf-8" standalone="yes"?> q种情况? 因ؓ ServiceB#methodB 的事务属性ؓ PROPAGATION_REQUIRES_NEW, 所以两者不会发生Q何关p? ServiceA#methodA ?ServiceB#methodB 不会因ؓҎ的执行情况而媄响事务的l果, 因ؓ它们Ҏ是两个事务, ?ServiceB#methodB 执行?ServiceA#methodA 的事务已l挂起了 (关于事务挂v的内容已l超Z本文的讨? 有时间我会再写一些挂L文章) . ServiceB#methodB 如果 rollback, 那么内部事务(?ServiceB#methodB) 回滚到它执行前?SavePoint(注意, q是本文中第一ơ提到它, 潜套事务中最核心的概?, 而外部事??ServiceA#methodA) 可以有以下两U处理方? q种方式也是潜套事务最有h值的地方, 它vC分支执行的效? 如果 ServiceB.methodB p|, 那么执行 ServiceC.methodC(), ?ServiceB.methodB 已经回滚到它执行之前?SavePoint, 所以不会生脏数据(相当于此Ҏ从未执行q?, q种Ҏ可以用在某些特D的业务? ?PROPAGATION_REQUIRED ?PROPAGATION_REQUIRES_NEW 都没有办法做到这一? (题外?: 看到q种代码, g似曾相识, 惌v?prototype.js 中的 Try 函数 )
PROPAGATION_REQUIRED -- 支持当前事务Q如果当前没有事务,新Z个事务。这是最常见的选择?nbsp;
PROPAGATION_SUPPORTS -- 支持当前事务Q如果当前没有事务,׃非事务方式执行?nbsp;
PROPAGATION_MANDATORY -- 支持当前事务Q如果当前没有事务,抛出异常?nbsp;
PROPAGATION_REQUIRES_NEW -- 新徏事务Q如果当前存在事务,把当前事务挂赗?nbsp;
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?nbsp;
PROPAGATION_NEVER -- 以非事务方式执行Q如果当前存在事务,则抛出异常?nbsp;
PROPAGATION_NESTED -- 如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIREDcM的操作?nbsp;
前六个策略类gEJB CMTQ第七个QPROPAGATION_NESTEDQ是Spring所提供的一个特D变量?nbsp;
它要求事务管理器或者用JDBC 3.0 Savepoint API提供嵌套事务行ؓQ如Spring的DataSourceTransactionManagerQ?nbsp;
在我所见过的误解中, 最常见的是下面q种:
假如有两个业务接?nbsp;ServiceA ?nbsp;ServiceB, 其中 ServiceA 中有一个方法实现如?nbsp;
/**
* 事务属性配|ؓ PROPAGATION_REQUIRED
*/
void methodA() {
// 调用 ServiceB 的方?nbsp;
ServiceB.methodB();
}
那么如果 ServiceB ?nbsp;methodB 如果配置了事? 必配|ؓ PROPAGATION_NESTED
q种x可能害了不少? 认ؓ Service 之间应该避免互相调用, 其实Ҏ不用担心q点QPROPAGATION_REQUIRED 已经说得很明?
如果当前U程中已l存在事? Ҏ调用会加入此事务, 果当前没有事务,新Z个事? 所?ServiceB#methodB() 的事务只要遵循最普通的规则配置?PROPAGATION_REQUIRED 卛_, 如果 ServiceB#methodB (我们UC为内部事? Z文打下基) 抛了异常, 那么 ServiceA#methodA(我们UC为外部事? 如果没有Ҏ配置此异常时事务提交 (?+MyCheckedException的用?, 那么整个事务是一定要 rollback ? 什?Service 只能?Dao 之类的言论纯属无E之? spring 只负责配|了事务属性方法的拦截, 它怎么知道你这个方法是?Service q是 Dao ??
最Ҏ弄淆的其实?PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED, 那么q两U方式又有何区别? 我简单的译一?Juergen Hoeller 的话 :
PROPAGATION_REQUIRES_NEW 启动一个新? 不依赖于环境?"内部" 事务. q个事务被完全 commited ?rolled back 而不依赖于外部事? 它拥有自q隔离范围, 自己的锁, {等. 当内部事务开始执行时, 外部事务被挂v, 内务事务l束? 外部事务l执?
另一斚w, PROPAGATION_NESTED 开始一?"嵌套? 事务, 它是已经存在事务的一个真正的子事? 潜套事务开始执行时, 它将取得一?savepoint. 如果q个嵌套事务p|, 我们回滚到?savepoint. 潜套事务是外部事务的一部分, 只有外部事务l束后它才会被提?
由此可见, PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED 的最大区别在? PROPAGATION_REQUIRES_NEW 完全是一个新的事? ?PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会?commit, q个规则同样适用?roll back.
那么外部事务如何利用嵌套事务?savepoint Ҏ呢, 我们用代码来说话ServiceA {
/**
* 事务属性配|ؓ PROPAGATION_REQUIRED
*/
void methodA() {
ServiceB.methodB(); }
}
ServiceB {
/**
* 事务属性配|ؓ PROPAGATION_REQUIRES_NEW
*/
void methodB() {
}
}
ServiceA {
/**
* 事务属性配|ؓ PROPAGATION_REQUIRED
*/
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
/**
* 事务属性配|ؓ PROPAGATION_NESTED
*/
void methodB() {
}
}
1. 改写 ServiceA 如下
ServiceA {
/**
* 事务属性配|ؓ PROPAGATION_REQUIRED
*/
void methodA() {
try {
ServiceB.methodB();
} catch (SomeException) {
// 执行其他业务, ?nbsp;ServiceC.methodC();
}
}
}
2. 代码不做M修改, 那么如果内部事务(?ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前?SavePoint(在Q何情况下都会如此), 外部事务(?ServiceA#methodA) 根据具体的配置军_自己?commit q是 rollback (+MyCheckedException).
上面大致讲述了潜套事务的使用场景, 下面我们来看如何?spring 中?PROPAGATION_NESTED, 首先来看 AbstractPlatformTransactionManager
JdbcTransactionObjectSupport 告诉我们必须要满两个条件才?createSavepoint :
2. java.sql.Savepoint 必须存在, ?jdk 版本?1.4+
3. Connection.getMetaData().supportsSavepoints() 必须?true, ?jdbc drive 必须支持 JDBC 3.0
保以上条g都满_, 你就可以试使用 PROPAGATION_NESTED ?
]]>
~存
Hibernate中用二U缓?/font>
Hiberante.cfg.xml
ehcache.xml配置
查询~存
~存与数据库同步
使用二~存的前|条?/font>