目录
- 1. 简介
- 2. TransactionTemplate 方式
- 3. TransactionManager 方式
- 4. 事务传播行为
- 5. 事务隔离级别
- 6. 最佳实践
- 7. 常见问题与解决方案
1. 简介
编程式事务管理是通过编写代码来管理事务,相对于声明式事务(@Transactional注解),它提供了更细粒度的事务控制。在 SpringBoot 中,主要有两种实现方式:
- 使用 TransactionTemplate
- 直接使用 TransactionManager
2. TransactionTemplate 方式
TransactionTemplate 是最简单的编程式事务实现方式,它对底层事务 API 进行了封装,使用起来更加便捷。
2.1 基本配置
@Configuration
public class TransactionConfig {@Autowiredprivate PlatformTransactionManager transactionManager;@Beanpublic 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 {@Autowiredprivate TransactionTemplate transactionTemplate;@Autowiredprivate 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 {@Autowiredprivate PlatformTransactionManager transactionManager;@Autowiredprivate 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 {@Autowiredprivate PlatformTransactionManager transactionManager;@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate TransactionHelper transactionHelper;public void doBusiness() {transactionHelper.executeInTransactionWithoutResult(status -> {// 业务逻辑});}
}
7. 常见问题与解决方案
7.1 事务超时处理
@Service
public class TimeoutExample {@Autowiredprivate 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 {@Autowiredprivate 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)可能是更好的选择。只有在需要特别精细的事务控制时,才考虑使用编程式事务。