spring事务的配置以及事务传播机制和相关的测试demo

在实际项目中为了保证数据的一致性,事务是非常重要的,而spring对事务的支持方便了我们对事务相关操作的开发.

 

事务的配置方式


spring支持编程式事务管理和声明式事务管理两种方式。
   编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
  声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
  声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

 

 

事务传播机制

标题
名称作用
REQUIRED
支持当前事务,如果当前没有事务,则新建事务;
如果当前存在事务,则加入当前事务,合并成一个事务

 

SUPPORTS
如果当前存在事务,则加入事务。 
如果当前不存在事务,则以非事务方式运行,这个和不写没区别
REQUIRES_NEW
新建事务,如果当前存在事务,则把当前事务挂起
这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交
NOT_SUPPORTED
该传播机制不支持事务,如果外层存在事务则挂起,执行完当前代码,则恢复外层事务,无论是否异常都不会回滚当前的代码
NEVER该传播机制不支持外层事务,即如果外层有事务就抛出异常
MANDATORY与NEVER相反,如果外层没有事务,则抛出异常
NESTED

如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交
如果当前没有事务,则新建事务
如果它异常,父级可以捕获它的异常而不进行回滚,正常提交(这点验证失败)
但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别

 

 

 

 

 

 

 

 

 

 

 

 

相关的测试

1、REQUIRED

a、如果inserA(有事务)当inserA调用inserB(无事务)时,inserB的是否有事务?

运行结果如下:

  结果:如果inserA(有事务)当inserA调用inserB(无事务)时,他会给inserB创建一个事务,并合并成一个事务.

b、如果当inserA(无事务)调用insertB(有事务)时,那么insertB的事务会执行吗?

运行结果:

结果:如果当inserA(无事务)调用insertB(有事务)时,insertB的事务是不会执行的事务回滚的,即insertB的事务不起作用

结论:

支持当前事务,如果当前没有事务,则新建事务;
如果当前存在事务,则加入当前事务,合并成一个事务

 

 

2、SUPPORTS

1、如果当inserA(required)调用insertB(supports)时,insertB的事务会回滚吗?

执行结果:

结果:如果当inserA(required)调用insertB(supports)时,insertB的事务会回滚.

b、如果当inserA(无事务)调用insertB(supports)时,insertB的事务会回滚吗?

结果如下:

结论:如果当inserA(无事务)调用insertB(supports)时,insertB的事务不会回滚

 

c、如果当inserA(supports)调用insertB(supports)时,insertB的事务会回滚吗?

结果如下:

结果:如果当inserA(supports)调用insertB(supports)时,insertB的事务不会回滚

 

d、如果当inserA(supports)调用insertB(required)时,insertB的事务会回滚吗?

结果如下:

结果:如果当inserA(supports)调用insertB(supports)时,insertB的事务不会回滚

 

结论

如果当前存在事务,则加入事务。
如果当前不存在事务,则以非事务方式运行,这个和不写没区别

 

REQUIRES_NEW

a、如果当insertLog(无事务)调用insertLogB(事务REQUIRES_NEW)时,会怎样?

结果如下:

结果:

如果当insertLog(无事务)调用insertLogB(事务REQUIRES_NEW)时,insertLogB创建了事务,并且insertLogB回滚事务,只有user的数据插入成功.

 

b、如果当insertLog(事务REQUIRES_NEW)调用insertLogB(无事务)时,会怎样?

结果如下:

结果:如果当insertLog(事务REQUIRES_NEW)调用insertLogB(无事务)时,insertLog创建了事务,并且insertLogB也创建了事务,并合并的了事务,且因报错,而回滚数据了.

 

c、如果当insertLog(事务REQUIRES)调用insertLogB(事务REQUIRES_NEW)时,会怎样?

结果如下:

结果:如果当insertLog(事务REQUIRES)调用insertLogB(事务REQUIRES_NEW)时,insertLogB独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交

 

总结

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

这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交

 

NOT_SUPPORTED

a、如果当insertLog(无事务)调用insertLogB(无事务NOT_SUPPORTED)时,会怎样?

结果如下:

结果:  如果当insertLog(无事务)调用insertLogB(无事务NOT_SUPPORTED)时,以非事务方式运行

 

b、如果当insertLog(事务)调用insertLogB(无事务NOT_SUPPORTED)时,会怎样?

结果如下:

结果:如果当前存在事务,则把当前事务挂起

总结

以非事务方式运行

如果当前存在事务,则把当前事务挂起

 

NEVER

a、如果当insertLog(无事务)调用insertLogB(事务NEVER)时,会怎样?

结果如下:

结果:如果当insertLog(无事务)调用insertLogB(事务NEVER)时,会正常执行,

 

b、如果当insertLog(有事务)调用insertLogB(事务NEVER)时,会怎样?

结果如下:

结果:如果当insertLog(required)调用insertLogB(事务NEVER)时,使用事务NEVER会报异常,并且会回滚数据.

总结

该传播机制不支持外层事务,即如果外层有事务就抛出异常

 

 

MANDATORY

a、如果当insertLog(有事务)调用insertLogB(事务MANDATORY)时,会怎样?

结果如下:

结果:正常执行

 

 

b、如果当insertLog(无事务)调用insertLogB(事务MANDATORY)时,会怎样?

结果如下:

结果:如果当insertLog(无事务)调用insertLogB(事务MANDATORY)时 ,会报异常

结论:

与NEVER相反,如果外层没有事务,则抛出异常

 

NESTED

  

a、如果当insertLog(无事务)调用insertLogB(事务NESTED)时,会怎样?

结果如下:

结果:如果当insertLog(无事务)调用insertLogB(事务NESTED)时,如果当前没有事务,则新建事务,并且insertLogB回滚了数据

b、如果当insertLog(有事务,有异常)调用insertLogB(事务NESTED)时,会怎样?

结果如下:

结果: 如果当insertLog(有事务)调用insertLogB(事务NESTED)时,说明数据回滚了,即自方法正常,父方法有异常的情况下,全部回滚

c、如果当insertLog(有事务)调用insertLogB(事务NESTED,有异常)时,会怎样?

 

结果如下:

结果:如果当insertLog(有事务)调用insertLogB(事务NESTED,有异常)时,数据全部回滚.

 

总结

如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交
如果当前没有事务,则新建事务
如果它异常,父级可以捕获它的异常而不进行回滚,正常提交
但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别

 

测试源码在GitHub上spring-framework下mySpring项目的com.lquan.trans包下(欢迎大家多多给意见,谢谢)

 

可参考,方便记忆

https://www.cnblogs.com/libin2015/p/12556163.html

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
事务隔离级别是指多个事务并发执行时,一个事务对其他事务的可见性和影响程度的控制。Spring框架支持四个事务隔离级别: 1. 未提交读(READ UNCOMMITTED):最低级别,一个事务可以读取未提交的数据,会导致脏读,不可重复读和幻读问题的出现。 2. 提交读(READ COMMITTED):一个事务只能读取已提交的数据,可以避免脏读问题,但可能导致不可重复读和幻读问题。 3. 可重复读(REPEATABLE READ):在一个事务中多次读取同一数据时,结果保持一致,避免了不可重复读问题。但仍然可能存在幻读问题。 4. 串行化(SERIALIZABLE):最高级别,通过确保事务串行执行来避免脏读、不可重复读和幻读问题。但会降低并发性能。 传播机制是指在调用多个事务方法时,如何处理事务传播。Spring框架提供七种传播行为: 1. REQUIRED:如果当前没有事务,就创建一个新事务;如果已存在事务,则加入该事务。 2. SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方法执行。 3. MANDATORY:强制要求存在当前事务,如果没有事务就抛出异常。 4. REQUIRES_NEW:创建一个新事务,并暂停当前事务(如果有)。 5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。 6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。 7. NESTED:在当前事务的控制下执行一个嵌套事务,如果不存在当前事务,则创建一个新事务。嵌套事务可以独立提交或回滚,但在外部事务提交时才会生效。 通过选择合适的事务隔离级别和传播机制,可以确保事务的数据一致性、安全性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值