什么场景下会触发?
在 Spring 中,调用 setRollbackOnly()
方法会将当前事务标记为 rollback-only,表示事务只能回滚,不能提交。这种情况通常发生在以下情景中:
-
业务逻辑判断:在方法中根据某些业务逻辑的判断,确定当前事务应该回滚而不是提交时,可以调用
setRollbackOnly()
方法将事务标记为 rollback-only。例如,在某些条件下,业务需要取消当前事务的执行并回滚。 -
异常处理:当方法中发生了异常,但异常被捕获并处理后,根据业务逻辑需要将当前事务标记为 rollback-only,以确保事务回滚而不是提交。通常在捕获异常后,根据异常的类型或其他条件,决定是否将事务标记为 rollback-only。
-
外部条件:外部条件可能导致事务需要回滚,例如与外部系统的交互失败、数据一致性问题等情况下,可以将事务标记为 rollback-only。
总的来说,调用 setRollbackOnly()
方法通常是为了在事务执行过程中明确指示事务应该回滚而不是提交。这样可以确保事务在特定条件下的一致性和完整性。
举个例子
当某个订单支付失败时,需要将订单的支付状态设置为失败,并且将库存恢复,以保持系统数据的一致性。在这种情况下,我们可以使用 setRollbackOnly()
方法将事务标记为 rollback-only,以确保事务回滚。
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryService inventoryService;
@Transactional
public void processOrderPayment(Order order) {
try {
// 进行订单支付操作
// 如果支付失败,抛出 PaymentFailedException
processPayment(order);
} catch (PaymentFailedException e) {
// 支付失败处理逻辑
// 设置订单支付状态为失败
order.setStatus(OrderStatus.PAYMENT_FAILED);
orderRepository.save(order);
// 恢复库存
inventoryService.revertInventory(order.getItems());
// 将事务标记为 rollback-only
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
private void processPayment(Order order) throws PaymentFailedException {
// 实际支付逻辑,可能会抛出 PaymentFailedException
}
}
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
org.springframework.transaction.interceptor.TransactionAspectSupport#currentTransactionStatus
org.springframework.transaction.interceptor.TransactionAspectSupport#currentTransactionInfo
org.springframework.transaction.support.AbstractTransactionStatus#setRollbackOnly
最终在申明式事务commit逻辑中会进行判断(方法没有抛出异常-commit逻辑中会进行rollBack)
所以:
不要再认为:只要方法执行成功,没有出现异常,那么方法上面的事务一定会执行提交。这个并不是绝对的!