在 Java 开发中,事务管理是保证数据一致性的核心机制,尤其是在 Spring 框架中,@Transactional注解的使用极大简化了事务配置。然而,在实际开发中,事务常常会因为一些细节问题而失效,导致数据异常。本文将详细解析 Java 事务失效的八大场景,每个场景都提供代码示例与对应的修复方案。
一、事务方法非 public 修饰
失效原理
Spring 的@Transactional注解默认只对public方法生效。这是因为 Spring AOP 在实现事务管理时,无论是 JDK 动态代理还是 CGLIB 代理,都无法对非 public 方法(private、protected、默认访问权限)进行有效的事务增强。
失效代码
java运行
@Service
public class UserService {
// 非public方法,事务注解失效
@Transactional
void updateUser(Long id) {
userMapper.updateStatus(id, 1);
}
}
修复方案
将事务方法修改为public访问权限。
修复后代码
java运行
@Service
public class UserService {
// 修改为public方法,事务生效
@Transactional
public void updateUser(Long id) {
userMapper.updateStatus(id, 1);
}
}
二、异常被捕获且未重新抛出
失效原理
Spring 事务默认仅在遇到未捕获的RuntimeException或Error时触发回滚。如果方法内部使用try-catch捕获了异常且未重新抛出,事务管理器会认为没有异常发生,从而不会执行回滚操作。
失效代码
java运行
@Service
public class OrderService {
@Transactional
public void createOrder(Order order) {
try {
orderMapper.insert(order);
// 模拟异常
int i = 1 / 0;
} catch (Exception e) {
// 捕获异常但未抛出,事务不会回滚
log.error("创建订单失败", e);
}
}
}
修复方案
方案一:捕获异常后重新抛出
方案二:使用TransactionAspectSupport手动触发回滚
修复后代码(方案一)
java运行
@Service
public class OrderService {
@Transactional
public void createOrder(Order order) {
try {
orderMapper.insert(order);
// 模拟异常
int i = 1 / 0;
} catch (Exception e) {
log.error("创建订单失败", e);
// 重新抛出异常,触发事务回滚
throw new RuntimeException("创建订单失

最低0.47元/天 解锁文章
1329

被折叠的 条评论
为什么被折叠?



