SpringBoot 编程式事务使用及两种实现方式
作者:lzz的编码时刻
编程式事务管理是通过编写代码来管理事务,相对于声明式事务(@Transactional注解),它提供了更细粒度的事务控制,这篇文章主要介绍了SpringBoot 编程式事务使用及两种实现方式,需要的朋友可以参考下
1. 简介
编程式事务管理是通过编写代码来管理事务,相对于声明式事务(@Transactional注解),它提供了更细粒度的事务控制。在 SpringBoot 中,主要有两种实现方式:
- 使用 TransactionTemplate
- 直接使用 TransactionManager
2. TransactionTemplate 方式
TransactionTemplate 是最简单的编程式事务实现方式,它对底层事务 API 进行了封装,使用起来更加便捷。
2.1 基本配置
@Configuration public class TransactionConfig { @Autowired private PlatformTransactionManager transactionManager; @Bean public TransactionTemplate transactionTemplate() { TransactionTemplate template = new TransactionTemplate(); template.setTransactionManager(transactionManager); // 设置默认的事务传播行为 template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 设置默认的事务隔离级别 template.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT); // 设置默认超时时间 template.setTimeout(30); return template; } }
2.2 基本使用示例
@Service @Slf4j public class UserService { @Autowired private TransactionTemplate transactionTemplate; @Autowired private UserRepository userRepository; public User createUser(User user) { // 使用 execute 方法执行有返回值的事务操作 return transactionTemplate.execute(status -> { try { User savedUser = userRepository.save(user); // 模拟其他操作 updateUserProfile(savedUser); return savedUser; } catch (Exception e) { // 手动标记事务回滚 status.setRollbackOnly(); log.error("创建用户失败", e); throw new RuntimeException("创建用户失败", e); } }); } public void batchCreateUsers(List<User> users) { // 使用 executeWithoutResult 方法执行无返回值的事务操作 transactionTemplate.executeWithoutResult(status -> { try { for (User user : users) { userRepository.save(user); } } catch (Exception e) { status.setRollbackOnly(); log.error("批量创建用户失败", e); throw new RuntimeException("批量创建用户失败", e); } }); } }
3. TransactionManager 方式
直接使用 TransactionManager 提供了更细粒度的事务控制,但使用起来相对复杂。
3.1 基本使用示例
@Service @Slf4j public class OrderService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private OrderRepository orderRepository; public Order createOrder(Order order) { // 定义事务属性 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); def.setTimeout(30); // 获取事务状态 TransactionStatus status = transactionManager.getTransaction(def); try { // 执行业务逻辑 Order savedOrder = orderRepository.save(order); // 处理订单相关的其他操作 processOrderDetails(savedOrder); // 提交事务 transactionManager.commit(status); return savedOrder; } catch (Exception e) { // 回滚事务 transactionManager.rollback(status); log.error("创建订单失败", e); throw new RuntimeException("创建订单失败", e); } } }
3.2 嵌套事务示例
@Service @Slf4j public class PaymentService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private PaymentRepository paymentRepository; public void processPayment(Payment payment) { // 外部事务定义 DefaultTransactionDefinition outerDef = new DefaultTransactionDefinition(); outerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus outerStatus = transactionManager.getTransaction(outerDef); try { // 外部事务操作 paymentRepository.save(payment); // 内部事务定义 DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition(); innerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); TransactionStatus innerStatus = transactionManager.getTransaction(innerDef); try { // 执行内部事务操作 processPaymentDetails(payment); transactionManager.commit(innerStatus); } catch (Exception e) { // 回滚内部事务 transactionManager.rollback(innerStatus); log.error("支付详情处理失败", e); throw e; } // 提交外部事务 transactionManager.commit(outerStatus); } catch (Exception e) { // 回滚外部事务 transactionManager.rollback(outerStatus); log.error("支付处理失败", e); throw new RuntimeException("支付处理失败", e); } } }
4. 事务传播行为
在编程式事务中,我们可以精确控制事务的传播行为:
@Service public class TransactionPropagationExample { @Autowired private TransactionTemplate transactionTemplate; public void demonstratePropagation() { // REQUIRED 传播行为 TransactionTemplate requiredTemplate = new TransactionTemplate(transactionTemplate); requiredTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // REQUIRES_NEW 传播行为 TransactionTemplate requiresNewTemplate = new TransactionTemplate(transactionTemplate); requiresNewTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 嵌套使用不同的传播行为 requiredTemplate.execute(outerStatus -> { // 外部事务逻辑 requiresNewTemplate.execute(innerStatus -> { // 内部事务逻辑(新的事务) return null; }); return null; }); } }
5. 事务隔离级别
示例展示如何设置不同的事务隔离级别:
@Service public class TransactionIsolationExample { @Autowired private PlatformTransactionManager transactionManager; public void demonstrateIsolation() { // 读已提交隔离级别 DefaultTransactionDefinition readCommittedDef = new DefaultTransactionDefinition(); readCommittedDef.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); TransactionStatus readCommittedStatus = transactionManager.getTransaction(readCommittedDef); try { // 业务逻辑 transactionManager.commit(readCommittedStatus); } catch (Exception e) { transactionManager.rollback(readCommittedStatus); throw e; } // 可重复读隔离级别 DefaultTransactionDefinition repeatableReadDef = new DefaultTransactionDefinition(); repeatableReadDef.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ); // ... 类似的事务处理逻辑 } }
6. 最佳实践
6.1 事务模板封装
创建一个通用的事务处理模板:
@Component @Slf4j public class TransactionHelper { @Autowired private TransactionTemplate transactionTemplate; public <T> T executeInTransaction(TransactionCallback<T> action) { try { return transactionTemplate.execute(action); } catch (Exception e) { log.error("事务执行失败", e); throw new RuntimeException("事务执行失败", e); } } public void executeInTransactionWithoutResult(Consumer<TransactionStatus> action) { try { transactionTemplate.executeWithoutResult(action); } catch (Exception e) { log.error("事务执行失败", e); throw new RuntimeException("事务执行失败", e); } } } // 使用示例 @Service public class BusinessService { @Autowired private TransactionHelper transactionHelper; public void doBusiness() { transactionHelper.executeInTransactionWithoutResult(status -> { // 业务逻辑 }); } }
7. 常见问题与解决方案
7.1 事务超时处理
@Service public class TimeoutExample { @Autowired private TransactionTemplate transactionTemplate; public void handleTimeout() { TransactionTemplate timeoutTemplate = new TransactionTemplate(transactionTemplate); timeoutTemplate.setTimeout(5); // 设置5秒超时 try { timeoutTemplate.execute(status -> { // 可能超时的业务逻辑 return null; }); } catch (TransactionTimedOutException e) { // 处理超时异常 log.error("事务执行超时", e); throw new RuntimeException("事务执行超时", e); } } }
7.2 异常处理最佳实践
@Service public class ExceptionHandlingExample { @Autowired private TransactionTemplate transactionTemplate; public void handleExceptions() { try { transactionTemplate.execute(status -> { try { // 业务逻辑 return null; } catch (BusinessException e) { // 业务异常,标记回滚 status.setRollbackOnly(); throw e; } catch (Exception e) { // 其他异常,标记回滚 status.setRollbackOnly(); throw new RuntimeException("未预期的错误", e); } }); } catch (Exception e) { // 统一异常处理 handleException(e); } } private void handleException(Exception e) { if (e instanceof BusinessException) { // 处理业务异常 log.warn("业务异常: {}", e.getMessage()); } else { // 处理系统异常 log.error("系统异常", e); } throw e; } }
虽然编程式事务提供了更细粒度的控制,但在大多数情况下,声明式事务(@Transactional)可能是更好的选择。只有在需要特别精细的事务控制时,才考虑使用编程式事务。
到此这篇关于SpringBoot 编程式事务使用的文章就介绍到这了,更多相关SpringBoot 编程式事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!