【问题标题】:Transaction marked as rollback-only with unknown reason交易标记为仅回滚,原因不明
【发布时间】:2020-05-08 05:09:00
【问题描述】:

我有一些类似下面的代码。

public class ServiceImpl implements Service
{
    @Transactional
    public myObject methodOne()
    {
        if (myCondition)
          return methodTwo();
        else 
          anotherMethod();
    }

    public myObject methodTwo()
    {
        int retryCount = 1;
        myObject myObject = null;
        while (retryCount <= 10) {
            try {
                myObject = repository.save();
                break;
            } catch (DataIntegrityViolationException ignored) {
                retryCount++;
            }
        }
        if (myObject == null){
            throw new MyException();
        }
    }
}

但它会抛出异常

事务静默回滚,因为它已被标记为 仅回滚

即使我在methodTwo()myObject != null 中也遇到了。谁能帮帮我!!!

【问题讨论】:

    标签: java spring transactions spring-data-jpa


    【解决方案1】:

    似乎是由于子事务中的回滚规则。

    methodTwo 怎么样返回myObject 并检查methodOne

    public class ServiceImpl implements Service
    {
        @Transactional
        public myObject methodOne()
        {
            myObject myObject = methodTwo()'
            if (myObject == null){
                throw new MyException();
            }
    
            return myObject;
        }
    
        public myObject methodTwo()
        {
            int retryCount = 1;
            myObject myObject = null;
            while (retryCount <= 10) {
                try {
                    myObject = repository.save();
                    break;
                } catch (DataIntegrityViolationException ignored) {
                    retryCount++;
                }
            }
            return myObject;
        }
    }
    

    【讨论】:

      【解决方案2】:

      事务中的任何RuntimeExceptionSpring 意识到,都会将该事务标记为回滚。

      考虑到repository.save() 的事务传播是REQUIRED 并且对repository.save() 的调用导致DataIntegrityViolationExceptionRuntimeException 的子类,即使处理了事务也会标记为回滚/抓到methodTwo()

      noRollbackFor/noRollbackForClassName@Transactional 属性可以用来控制回滚行为。例如,

      @Transactional(noRollbackFor=DataIntegrityViolationException.class)
      

      注意:Spring 意识到的 RuntimeExceptions 是,如果 RuntimeException 被显式抛出并在同一方法中处理,Spring 将不会意识到该异常并且不会标记周围回滚事务。 RuntimeException 应该通过 spring 代理传播以发生这种情况,这发生在您的用例中。

      【讨论】:

      • 感谢您的帮助,我只是添加了@org.springframework.transaction.annotation.Transactional(noRollbackFor = {DataIntegrityViolationException.class}) 但仍然抛出上述异常
      • 能否将完整的堆栈跟踪更新为问题。异常将被抛出,但该异常不会发生回滚,这是我们使用该注释属性所告诉的。我假设抛出的异常将是不同的。另外,您能否检查一下 answer 是否对您有帮助。
      猜你喜欢
      • 2013-10-21
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2014-10-29
      • 2012-07-10
      • 1970-01-01
      相关资源
      最近更新 更多