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 编程式事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
springboot jasypt2.x与jasypt3.x的使用方式
在软件开发中,将配置文件中的敏感信息(如数据库密码)进行加密是保障安全的有效手段,jasypt框架提供了这一功能,支持通过加密工具类或命令行工具生成密文,并通过修改配置文件和启动参数的方式使用密文和密钥,这样即便配置文件被泄露2024-09-09
jstl之map,list访问遍历以及el表达式map取值的实现
下面小编就为大家带来一篇jstl之map,list访问遍历以及el表达式map取值的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-03-03
IntelliJ IDEA 2023.1.4 无法刷新Maven项目模块的问题及解决方法
这篇文章主要介绍了如何排查 IDEA 自身报错问题,本文以IntelliJ IDEA 2023.1.4无法刷新项目Maven模块的问题为例,给大家详细讲解,需要的朋友可以参考下2023-08-08
解决SpringCloud下spring-boot-maven-plugin插件的打包问题
这篇文章主要介绍了SpringCloud下spring-boot-maven-plugin插件的打包问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-03-03
详解springboot+mybatis-plue实现内置的CRUD使用详情
这篇文章主要介绍了详解springboot+mybatis-plue实现内置的CRUD使用详情,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-07-07
Flutter 通过Clipper实现各种自定义形状的示例代码
这篇文章主要介绍了Flutter 通过Clipper实现各种自定义形状的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2019-12-12


最新评论