Spring的事务传播
事务传播
写在前面
Spring的事务是通过AOP这种代理的方式实现的。
事务传播就是多个事务方法相互调用时,事务如何在这些方法间传播。比如事务方法A调用了方法B,那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务执行造成影响,而方法A的事务对方法B的事务执行也有影响,这种影响就由两个方法定义的事务传播类型所决定。
spring中的事务传播定义了七种类型:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。这七种类型以枚举的形式存储在org.springframework.transaction.annotation
的Propagation
。
下面根据集体的例子来解释每一个情况。
假设现在有两个方法A和B,A会在ATable中插入一条数据,B会在BTable中插入一条数据。伪代码如下:
1 | // 将传入参数a存入ATable |
假设没有事务时,如下场景:
1 | public void testMain(){ |
这种情况下,a1和b1这两条数据会存入对用的数据库,而b2这条数据会因为异常而没有入库。
REQUIRED(Spring默认的事务传播)
如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务
使用场景如下:
1 |
|
这种情况下,数据库的状态会停留在没有执行这两个方法的状态。
testMain()
声明了事务,它执行时会创建事务,在执行testB()
的时候,它就会加入testMain()
的事务,而不会自己创建。
SUPPORTS
当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
1 | public void testMain(){ |
这种情况下,a1和b1会插入数据库,b2不会插入,因为testMain()
是没有事务的,所以执行testB()
方法时,无法加入其他的事务。
MANDATORY
当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
上面的代码在这种情况下,执行结果就是a1存储数据库,而b1和b2没有存入,因为testMain()
没有事务而产生报错。
REQUIRES_NEW
创建一个新事务,如果存在当前事务,则挂起该事务。可以理解为在执行时,不论当前是否存在事务,总是会新建一个事务。
1 |
|
这种情况下,a1没有存入成功,而b1和b2会存入成功。因为testB()
会新建一个事务,而不是采用testMain()
的事务。
NOT_SUPPORTED
始终以非事务方式执行,如果当前存在事务,则挂起当前事务,可以理解为始终不执行事务。
NEVER
不使用事务,如果当前事务存在,则抛出异常