Spring中的事务传播属性详解
在使用Spring时 大部分会用到他的声明式事务 简单的在配置文件中进行一些规则配置 利用Spring的AOP功能就能轻松搞定事务问题 这里面就涉及到一个事务的传播属性问题Propagation 它在TransactionDefinition接口中定义 以供PlatfromTransactionManager使用 PlatfromTransactionManager是spring事务管理的核心接口
TransactionDefinition
public interface TransactionDefinition {
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
}
getTimeout()方法 它返回事务必须在多少秒内完成
isReadOnly() 事务是否只读 事务管理器能够根据这个返回值进行优化 确保事务是只读的
getIsolationLevel()方法返回事务的隔离级别 事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据
在TransactionDefinition接口中定义了五个不同的事务隔离级别 ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别 使用数据库默认的事务隔离级别 另外四个与JDBC的隔离级别相对应 ISOLATION_READ_UNMITTED 这是事务最低的隔离级别 它充许别外一个事务可以看到这个事务未提交的数据 这种隔离级别会产生脏读 不可重复读和幻像读
在TransactionDefinition接口 *** 有 种选项可用
PROPAGATION_REQUIRED 支持当前事务 如果当前没有事务 就新建一个事务 这是最常见的选择
PROPAGATION_SUPPORTS 支持当前事务 如果当前没有事务 就以非事务方式执行
PROPAGATION_MANDATORY 支持当前事务 如果当前没有事务 就抛出异常
PROPAGATION_REQUIRES_NEW 新建事务 如果当前存在事务 把当前事务挂起
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作 如果当前存在事务 就把当前事务挂起
PROPAGATION_NEVER 以非事务方式执行 如果当前存在事务 则抛出异常
PROPAGATION_NESTED 支持当前事务 新增Savepoint点 与当前事务同步提交或回滚
现在结合一个实例 应用以上各种传播属性来进行说明 首先声明两个bean ServiceA和ServiceB 其中ServiceB被引用
ServiceA {
void methodA() {
thodB();
}
}
ServiceB {
void methodB() {
}
}
接下来 我们就一一分析下
PROPAGATION_REQUIRED
加入当前正要执行的事务不在另外一个事务里 那么就起一个新的事务 比如说 thodB的事务级别定义为PROPAGATION_REQUIRED 那么由于执行thodA的时候 thodA已经起了事务 这时调用thodB thodB看到自己已经运行在thodA 的事务内部 就不再起新的事务 而假如thodA运行的时候发现自己没有在事务中 他就会为自己分配一个事务 这样 在thodA或者在thodB内的任何地方出现异常 事务都会被回滚 即使thodB的事务已经被 提交 但是thodA在接下来fail要回滚 thodB也要回滚
PROPAGATION_SUPPORTS
如果当前在事务中 即以事务的形式运行 如果当前不再一个事务中 那么就以非事务的形式运行
PROPAGATION_MANDATORY
必须在一个事务中运行 也就是说 他只能被一个父事务调用 否则 他就要抛出异常
PROPAGATION_REQUIRES_NEW
比如我们设计thodA的事务级别为PROPAGATION_REQUIRED thodB的事务级别为PROPAGATION_REQUIRES_NEW 那么当执行到thodB的时候 thodA所在的事务就会挂起 thodB会起一个新的事务 等待thodB的事务完成以后 他才继续执行 他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了 因为thodB是新起一个事务 那么就是存在 两个不同的事务 如果thodB已经提交 那么thodA失败回滚 thodB是不会回滚的 如果thodB失败回滚 如果他抛出的异常被thodA捕获 thodA事务仍然可能提交
PROPAGATION_NOT_SUPPORTED
当前不支持事务 比如thodA的事务级别是PROPAGATION_REQUIRED 而thodB的事务级别是PROPAGATION_NOT_SUPPORTED 那么当执行到thodB时 thodA的事务挂起 而他以非事务的状态运行完 再继续thodA的事务
PROPAGATION_NEVER
不能在事务中运行 假设thodA的事务级别是PROPAGATION_REQUIRED 而thodB的事务级别是PROPAGATION_NEVER 那么thodB就要抛出异常了
PROPAGATION_NESTED
理解Nested的关键是savepoint 他与PROPAGATION_REQUIRES_NEW的区别是 PROPAGATION_REQUIRES_NEW另起一个事务 将会与他的父事务相互独立 而Nested的事务和他的父事务是相依的 他的提交是要等和他的父事务一块提交的 也就是说 如果父事务最后回滚 他也要回滚的 而Nested事务的好处也是他有一个savepoint
ServiceA {
void methodA() {
try {
thodB();
} catch (Exception e) {
thodC();
}
}
}
lishixinzhi/Article/program/Java/ky/201311/28910