Spring事务与异常

  1. 在Spring的事务方法中,如果发生异常:
  • 异常不被try-catch捕获,此时事务管理器能感知到最初始的异常,故事务不能提交。
  • 异常被try-catch捕获并就地消化,此时事务管理器感知不到异常,故事务能提交。
  • 异常被try-catch捕获并再次手动抛出,此时事务管理器能感知到手动抛出的异常,故事务不能提交。
  • 异常被try-catch捕获并就地消化,同时手动显式地设置事务状态为RollbackOnly,TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();,事务不可提交。
  1. 带有事务传播行为的异常:
    最近在项目中遇到Transaction rolled back because it has been marked as rollback-only异常成因分析:
  • 方法outer()调用方法inner(),两个方法都有开启了事务,且方法inner();采用了默认的传播行为即required,在这种传播机制下,Spring发现方法inner();被方法outer();的事务包裹,inner()方法被融入outer()所在的外层事务中,相当于内外层共用一个事务。
  • 项目代码中,方法outer()里有人用try-catch包裹了对方法inner()的调用,并简单的就地消化异常,若方法inner()执行出错,就会将外层事务标记为rollback-only。
  • 但此时事务管理器由于没有感知到异常,就会继续执行逻辑,并打算继续提交交事务,但在真正提交外事务之际,才检测到外层事务状态已被标记为rollback-only,导致提交失败,所以就会抛出has been marked as rollback-only异常。
  • 这个异常源自事务管理器得到的事务状态与期望不一致,并且原始异常没有阻断逻辑的执行,而has been marked as rollback-only异常又没有反应真正的问题所在,所以需要加以修改并消除。
  • 消除方法还是要从事务与异常的关系出发,让事务管理器感知到发生异常的原始点位,具体做法:

1.不用try-catch包裹对子方法的调用。
2.捕获并转换,再手动抛出,以让事务管理器感知到异常的发生。

posted @ 2020-10-05 21:06  JaxYoun  阅读(871)  评论(0编辑  收藏  举报