Spring 声明式事务管理
TIP
Spring 声明式事务管理基于 AOP 实现,开发者只需通过注解声明事务边界,无需编写事务管理代码。
@Transactional 注解
java
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private InventoryDao inventoryDao;
@Transactional
public void createOrder(Order order) {
orderDao.insert(order);
inventoryDao.decrease(order.getProductId(), order.getQuantity());
// 事务中任一操作失败都会回滚
}
}事务传播行为
java
@Transactional(propagation = Propagation.REQUIRED) // 默认:支持当前事务,没有则创建
@Transactional(propagation = Propagation.REQUIRES_NEW) // 创建新事务,挂起当前事务
@Transactional(propagation = Propagation.NESTED) // 嵌套事务
@Transactional(propagation = Propagation.SUPPORTS) // 支持当前事务,没有则不开启
@Transactional(propagation = Propagation.NOT_SUPPORTED) // 以非事务方式执行
@Transactional(propagation = Propagation.NEVER) // 必须以非事务方式执行
@Transactional(propagation = Propagation.MANDATORY) // 必须在事务中执行事务隔离级别
java
@Transactional(isolation = Isolation.DEFAULT) // 默认:使用数据库默认级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Transactional(isolation = Isolation.READ_COMMITTED) // 推荐:防止脏读
@Transactional(isolation = Isolation.REPEATABLE_READ) // MySQL 默认
@Transactional(isolation = Isolation.SERIALIZABLE) // 最高级别,性能最差回滚规则
java
@Transactional(
rollbackFor = Exception.class, // 遇到 Exception 及其子类回滚
noRollbackFor = IllegalArgumentException.class // 遇到指定异常不回滚
)
public void transfer(Account from, Account to, BigDecimal amount) {
// ...
}事务失效的常见场景
java
// 1. 同一个类中方法调用(AOP 代理不生效)
@Service
public class OrderService {
public void processOrder() {
this.createOrder(); // 直接调用,事务不生效!
}
@Transactional
public void createOrder() {
// ...
}
}
// 解决方法:注入自身代理
@Service
public class OrderService {
@Autowired
private OrderService self; // 注入自身代理
public void processOrder() {
self.createOrder(); // 通过代理调用,事务生效
}
}
// 2. 非 public 方法
@Transactional // private 方法不会生效
private void save() { }
// 3. try-catch 吞掉异常
@Transactional
public void save() {
try {
// ...
} catch (Exception e) {
// 不抛出异常,事务不会回滚
}
}