提问人:Satej 提问时间:9/3/2023 更新时间:9/3/2023 访问量:51
即使处理了运行时异常,事务也会回滚
Transaction is rolled back even though runtime exception is handled
问:
正如你看到的下面的代码,我已经处理了运行时异常,并编写了一些代码来防止这个静止的事务被回滚,这让我感到惊讶。
我已经阅读了关于这个类似问题的答案,但我最终还是得到了这个问题。需要明确的解释和解决方案来解决这个问题。
[代码说明]
在下面的代码中,我试图保存一个 Event(Version 是我的 Events 表中的唯一键)类型的 obj,如果已经找到相同的版本,它会给我唯一的约束冲突异常。对于我的用例来说,这种拥有现有版本的行为是不可避免的,但是我可以增加版本并重新尝试。
[问题]
但是,我观察到的是,当它找到现有版本时,它会转到 catch 块,它确实会递增版本并尝试重试,最终它会成功。方法 m2() 最终被执行,m3() 和最后的 m1() 也是如此。
但是,我没有收到 201 响应,而是收到 500 错误,消息事务已回滚。
有什么方法可以处理这个问题?谢谢。
[代码]
@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());
}
}
}
答:
0赞
HassanUsman
9/3/2023
#1
在您的例子中,即使您捕获并重试保存操作,如果抛出异常,事务也不会提交,这就是您看到 .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
评论
0赞
Satej
9/3/2023
transactionManager.commit(status);- > 但是@Transactional也执行提交
0赞
HassanUsman
9/3/2023
你是绝对正确的,确保正确设置了@Transactional注释的传播行为。并注意可能存在的任何数据库锁,因为这些锁可能会影响事务行为。
评论
@Transactional(noRollbackFor = { UniqueConstraintViolationException .class })