Spring Data Jpa 即使处理了运行时异常,事务也会回滚

hpxqektj  于 12个月前  发布在  Spring
关注(0)|答案(1)|浏览(279)

正如你看到下面的代码,我已经处理了运行时异常,并编写了一些代码,以防止这个仍然是事务回滚到我的惊喜。
我已经读了一些关于这个类似问题的答案,但我最终还是得到了这个问题。需要明确的解释和解决方案,以解决这个问题,请。
[Code解释】
在下面的代码中,我试图保存一个Event类型的对象(Version是我的Events表中唯一的键),如果已经找到相同的版本,它会给我唯一的约束违反异常。对于我的用例来说,这种已经存在的版本的行为是不可避免的,但是我可以增加版本并重试。
[问题]
然而,我观察到的是,当它找到一个现有的版本时,它会进入catch块,它会增加版本并尝试重试,最后它成功了。

**但不是得到一个201响应,我得到了500错误消息transaction is rolled-back。

有什么方法可以解决这个问题?谢谢。
【代码】

@Transactional
void m1(Event event){

//DB write operation
m2(event);

//DB write operation
m3();

}

@Transactional
void m2(Event obj){

 boolean success = false;

 while(!success){

  try{

   eventRepo.save(event);
   success = true;

  } catch(UniqueConstraintViolationException e){

   event.setVersion(++event.getVersion());

   }

 }

}

字符串

ep6jt1vc

ep6jt1vc1#

在您的例子中,即使您捕获了UniqueConstraintViolationException并重新尝试保存操作,如果抛出异常,事务也不会提交,这就是您看到500 error的原因。
要处理这种情况,您可以使用programmatic transaction方法。以下是您如何做到这一点:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Autowired
private PlatformTransactionManager transactionManager;

void m1(Event event) {
    // Create a new transaction definition
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

    // Start a new transaction
    TransactionStatus status = transactionManager.getTransaction(def);

    try {
        // DB write operation
        m2(event);

        // DB write operation
        m3();

        // Commit the transaction if everything is successful
        transactionManager.commit(status);
    } catch (Exception e) {
        // Rollback the transaction if an exception occurs
        transactionManager.rollback(status);
    }
}

void m2(Event event) {
    boolean success = false;

    while (!success) {
        try {
            eventRepo.save(event);
            success = true;
        } catch (UniqueConstraintViolationException e) {
            event.setVersion(++event.getVersion());
        }
    }
}

字符串
这样,您可以在事务范围内进行handle exceptions和重试,而不会影响外部事务和causing a rollback。尝试一下,如果您仍然遇到任何问题,请告诉我。

相关问题