Java 事务注解@Transactional是用来标记一个方法需要被事务管理的,常用于对数据库进行操作时保证数据的一致性。在使用@Transactional标记方法时,我们可能会遇到回滚问题。
- @Transactional的默认回滚行为
首先介绍一下@Transactional默认的回滚行为。如果一个被@Transactional标记的方法执行过程中抛出了RuntimeException或者Error,该方法会执行事务回滚。例如:
@Transactional
public void testMethod() {
// some database(update, delete, insert) operations
if (1 == 1) {
throw new RuntimeException("test error");
}
}
上面的代码中,如果在进行数据库操作后,抛出了RuntimeException异常,则该事务会被回滚。
如果即使程序发生了异常但是该异常属于Exception类,该事务不会回滚,需要开发者自行处理异常。
- 在try catch中使用@Transactional注解
如果在被@Transactional标记的方法中有try catch语句块,那么异常应该在捕获后才能被事务管理器接管,从而达到回滚的目的。例如:
@Transactional
public void testMethod() {
try {
//some database(insert、delete、update) operations
} catch(Exception e) {
throw new RuntimeException("rollback", e);
}
}
上述代码中,使用try catch方式来捕获异常后抛出RuntimeException异常,该方法执行过程中,如果发生了Exception异常,该异常将会被捕获并被事务框架接管,从而进行事务回滚。
- 嵌套事务下@Transactional回滚问题
如果被@Transactional标记的方法调用了其他被@Transactional标记的方法,那么事务会进行嵌套。如果内层方法发生了异常,事务的回滚也会回溯到外层方法。例如:
@Service
public class OuterServiceImpl implements OuterService {
@Autowired
private InnerService innerService;
@Transactional
public void outerMethod() {
// some database(insert, delete, update) operations
innerService.innerMethod();
}
}
@Service
public class InnerServiceImpl implements InnerService {
@Transactional
public void innerMethod() {
// some database(insert, delete, update) operations
if (true) {
throw new RuntimeException("rollback");
}
}
}
上述代码中,如果innerService.innerMethod()方法抛出异常,则整个嵌套事务将会被回滚。
- 使用@Transactional注解需要注意的问题
@Transactional注解应该只用在当您确认异常可以安全被忽略的时候。在应用的底层事务管理层(比如在Hibernate、Spring JPA或是MyBatis模板层使用@Transactional)可以简化数据访问层的代码。
在使用@Transactional注解时,需要注意以下问题:
- 不要在无效场合使用回滚,执行上拉会对代码的健壮性产生影响
- 慎重使用嵌套事务,所有事务特性应该在transactional标签上进行指定并禁用自动提交
- 在尽可能空作用域内使用事务,以最小化锁定持续时间并最大化并行操作
以上是Java事务注解@Transactional回滚问题的完整攻略,希望能帮助您更好的使用事务管理。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 事务注解@Transactional回滚(try catch、嵌套)问题 - Python技术站