Transaction rolled bacj because it has been marked as rallback-only
时间: 2023-11-07 08:52:20 浏览: 40
当使用Spring的事务管理器时,如果一个内层事务在发生异常时被标记为rollback-only,那么在最外层事务提交时,会抛出"Transaction rolled back because it has been marked as rollback-only"这个异常。这个异常的原因是内层事务的异常导致事务被标记为需要回滚,但是外层事务的执行并没有检测到内层事务的回滚标记,因此在提交时触发了这个异常。
解决这个问题的方法有多种。一种方法是在外层事务中捕获并处理内层事务的异常,确保内层事务不会被标记为rollback-only。另一种方法是将内层事务和外层事务分别定义在不同的类中,这样就不会发生内层事务异常导致外层事务回滚的情况。
以下是一个示例代码,展示了如何解决这个问题:
@Service
public class A {
@Transactional(rollbackFor = Exception.class)
public void methodA() {
try {
methodB();
insert();
} catch (Exception e) {
System.out.println("异常抛出");
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void methodB() {
insert();
System.out.println(1 / 0);
}
}
在这个示例代码中,将methodA和methodB分别定义在不同的方法中,同时使用了Propagation.REQUIRES_NEW来定义methodB的事务传播方式。这样,在methodB发生异常时,只会回滚methodB的事务,而不会影响到methodA的事务。
另外,还可以使用@Transactional注解的noRollbackFor属性来指定不回滚的异常类型,从而避免出现"Transaction rolled back because it has been marked as rollback-only"异常。例如,可以将下面的代码添加到methodA方法上:
@Transactional(rollbackFor = Exception.class, noRollbackFor = RollbackException.class)
public void methodA() {
try {
methodB();
insert();
} catch (RollbackException e) {
System.out.println("异常抛出");
}
}
在这个示例代码中,如果methodB抛出了RollbackException异常,它的事务仍然会被回滚,但是不会导致外层事务回滚。这样就可以避免出现"Transaction rolled back because it has been marked as rollback-only"异常。
请注意,具体的解决方法应根据实际情况进行选择和调整。以上仅为一些建议和示例。