java

位置:IT落伍者 >> java >> 浏览文章

Spring中的事务传播属性详解


发布日期:2021年06月25日
 
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_UNCOMMITTED 这是事务最低的隔离级别它充许别外一个事务可以看到这个事务未提交的数据这种隔离级别会产生髒读不可重复读和幻像读

在TransactionDefinition接口中共有种选项可用

PROPAGATION_REQUIRED支持当前事务如果当前没有事务就新建一个事务这是最常见的选择

PROPAGATION_SUPPORTS支持当前事务如果当前没有事务就以非事务方式执行

PROPAGATION_MANDATORY支持当前事务如果当前没有事务就抛出异常

PROPAGATION_REQUIRES_NEW新建事务如果当前存在事务把当前事务挂起

PROPAGATION_NOT_SUPPORTED以非事务方式执行操作如果当前存在事务就把当前事务挂起

PROPAGATION_NEVER以非事务方式执行如果当前存在事务则抛出异常

PROPAGATION_NESTED支持当前事务新增Savepoint点与当前事务同步提交或回滚

现在结合一个实例应用以上各种传播属性来进行说明首先声明两个beanServiceA和ServiceB其中ServiceB被引用

ServiceA {

void methodA() {

thodB();

}

}

ServiceB {

void methodB() {

}

}

接下来我们就一一分析下

PROPAGATION_REQUIRED

加入当前正要执行的事务不在另外一个事务里那么就起一个新的事务比如说thodB的事务级别定义为PROPAGATION_REQUIRED 那么由于执行thodA的时候 thodA已经起了事务这时调用thodBthodB看到自己已经运行在thodA 的事务内部就不再起新的事务而假如thodA运行的时候发现自己没有在事务中他就会为自己分配一个事务 这样在thodA或者在thodB内的任何地方出现异常事务都会被回滚即使thodB的事务已经被 提交但是thodA在接下来fail要回滚thodB也要回滚

PROPAGATION_SUPPORTS

如果当前在事务中即以事务的形式运行如果当前不再一个事务中那么就以非事务的形式运行

PROPAGATION_MANDATORY

必须在一个事务中运行也就是说他只能被一个父事务调用否则他就要抛出异常

PROPAGATION_REQUIRES_NEW

比如我们设计thodA的事务级别为PROPAGATION_REQUIREDthodB的事务级别为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();

}

}

}

也就是说thodB失败回滚那么thodA会回滚到savepoint点上thodA可以选择另外一个分支比如 thodC继续执行来尝试完成自己的事务但是这个事务并没有在EJB标准中定义

上一篇:简单的Hibernate入门介绍

下一篇:Spring3.0中的AOP配置方法