事物生效,订单类内部更新订单
代码如下
以下代码1不生效,2生效
解决方案
1,外层方法加注解,内层不加
2,不要拆分方法,把更新订单操作放在带事物的大方法中
3,拆方法(内部),注入自己,用代理对象调用
4,拆方法(单独bean)
5,使用编程性事物
@Autowiredprivate TransactionTemplate transactionTemplate;
@Service
public class OrderService {public void updateOrder(Order order) {// 其他逻辑...this.updateOrderStatus(order); // 直接调用,事务不生效!}@Transactionalpublic void updateOrderStatus(Order order) {// 更新订单状态(期望事务生效,但实际不会)orderRepository.save(order);}
}
@Service
public class OrderService {@Transactional // 新增注解public void updateOrder(Order order) {// 其他逻辑...this.updateOrderStatus(order); // 直接调用}// 去掉了 @Transactional 注解public void updateOrderStatus(Order order) {orderRepository.save(order);}
}
代码2的回复
关键问题
事务是否会生效?
updateOrderStatus
是否会和updateOrder
在同一个事务中?
1. 事务是否生效?
✅ 事务会生效
因为
updateOrder
方法添加了@Transactional
,且是通过外部调用(如orderService.updateOrder()
)触发的。Spring 的 AOP 代理会拦截该方法,开启一个事务。
❗ 但有一个重要限制
updateOrderStatus
是通过this.updateOrderStatus()
直接调用的(自调用),不会经过 Spring 代理。因此,
updateOrderStatus
方法本身不会单独开启事务,但它的数据库操作会继承updateOrder
的事务。
2. updateOrderStatus
是否在同一个事务中?
✅ 是,在同一个事务中
虽然
updateOrderStatus
没有自己的@Transactional
注解,但它的数据库操作(如orderRepository.save(order)
)会默认加入当前线程绑定的事务(即updateOrder
开启的事务)。本质上,
updateOrder
和updateOrderStatus
的数据库操作是同一个事务的一部分。
3. 验证事务行为
(1)测试代码
java
@Transactional public void updateOrder(Order order) {orderRepository.save(order); // 操作1this.updateOrderStatus(order); // 操作2throw new RuntimeException("模拟异常"); // 触发回滚 }public void updateOrderStatus(Order order) {orderRepository.save(order); // 操作3 }
(2)预期结果
如果事务生效,操作1、操作2、操作3都会回滚(因为它们在同一个事务中)。
如果事务不生效,数据会被正常保存。
4. 关键结论
场景 | 事务是否生效 | 是否同一事务 |
---|---|---|
updateOrder 加 @Transactional | ✅ 生效 | ✅ 是 |
updateOrderStatus 去注解 + 自调用 | 继承外层事务 | ✅ 是 |
注意事项
自调用问题
虽然事务能生效,但直接
this.updateOrderStatus()
的调用方式不推荐,因为:如果未来
updateOrderStatus
需要独立事务(如REQUIRES_NEW
),这种写法无法实现。代码可维护性差(事务边界不清晰)。
推荐改进
如果不需要独立事务,直接合并逻辑到
updateOrder
:java
@Transactional public void updateOrder(Order order) {// 其他逻辑...orderRepository.save(order); // 直接操作 }
如果需要拆分方法,用代理对象调用:
java
@Autowired private OrderService self; // 注入代理@Transactional public void updateOrder(Order order) {self.updateOrderStatus(order); // 通过代理调用 }
5. 最终答案
你的代码中:
事务会生效,且
updateOrder
和updateOrderStatus
的操作在同一个事务中。但自调用(
this.xxx()
)是不推荐的写法,未来可能埋坑。
改进建议:
java
@Service public class OrderService {@Transactionalpublic void updateOrder(Order order) {// 其他逻辑...orderRepository.save(order); // 直接操作,避免拆分} }
或(如需强制拆分):
java
@Service public class OrderService {@Autowiredprivate OrderService self; // 注入代理@Transactionalpublic void updateOrder(Order order) {self.updateOrderStatus(order); // 通过代理调用}@Transactional // 可按需调整传播行为public void updateOrderStatus(Order order) {orderRepository.save(order);} }