• org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only


    完整的异常信息:

    org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

    字面意思:

    出现了不可预知的回滚异常,因为事务已经被标志位只能回滚,所以事务回滚了。

    解释:

           以下边代码举例

    class ServiceA{
            
            //传播属性设置为PROPAGATION_REQUIRED
            void methodA(){
                try{
                    serviceB.methodB();
                }catch (Exception e){
                    
                }
            }    
        }
        
        class ServiceB{
            
            //传播属性设置为PROPAGATION_REQUIRED
            void methodB(){
                
            }  
        }

    因为methodB的传播属性设置为PROPAGATION_REQUIRED,PROPAGATION_REQUIRED的意思是,当前有事务,则使用当前事务,当前无事务则创建事务。由于methodA的传播属性也为PROPAGATION_REQUIRED,所以methodA会创建一个事务,然后methodB与methodA使用同一个事务,methodB出现异常后,将当前事务标志位回滚,由于在methodA中做了trycatch处理,程序没有终止而是继续往下走,当事务commit时,check状态,发现,需要事务回滚,所以才会出现不可预知的事务异常:因为事务被标志位回滚,所以事务回滚。

    一言以概之,methodA与methodB共用一个事务,methodB将事务标志为回滚,methodA中commit这个事务,然后,出现事务已经被标志回滚(methodB标志的)的异常信息。

    修改:

    情况1:methodA与methodB在逻辑上不应该属于同一个事务,那么将methodB的事务传播属性修改为PROPAGATION_REQUIRES_NEW,这样,执行methodB时,会创建一个新的事务,不影响methodA中的事务。

    情况2:业务A与业务B在业务逻辑上就应该属于同一个事务,那么将methodA中的try catch去掉

    情况3:业务A与业务B在业务逻辑上就应该属于同一个事务,但是methodB的失败与否不能影响methodA的事务提交,那么仍然在methodA中try catch methodB,并将methodB设置为PROPAGATION_NESTED,它的意思是,methodB是一个子事务,有一个savepoint,失败时会回滚到savepoint,不影响methodA,如果成功则A、B一起提交,A与B都是一个事务,只是B是一个子事务

    总结:

    1、深入理解事务传播的各个状态含义,比如PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY、PROPAGATION_REQUIRES_NEW等

    2、最初我以为是由于spring配置文件中,methodA的事务设置为ready-only=true(只读事务)的原因,经过查询资料得知,只读事务与事务传播不冲突,是两个机制。只读事务,是一个特殊的事务,该事务内,只能是查询语句,不能含有修改、更新语句,数据库可能对只读事务做优化;传播属性是母方法与子方法之间的关系表达。

    3、注意,同一个类中,事务嵌套以最外层的方法为准,嵌套的事务失效;不同类中嵌套的事务才会生效;


    ————————————————
    版权声明:本文为CSDN博主「QQ_851228082」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/wangjun5159/article/details/48787397



  • 相关阅读:
    input中只能填数字的限制
    免登陆:保存登录页面的用户名密码,用md5对密码加密保存
    SQL 插入日期时间 变量值
    Debugger Exception Notification
    CoHTMLDocument
    json数组,随便测试
    显示时间的毫秒
    赋值后再调整动态数组的元素个数
    数据集和非数据感知控件使用
    FR报表 自动缩小的代码
  • 原文地址:https://www.cnblogs.com/funian/p/15209188.html
Copyright © 2020-2023  润新知