news 2026/4/15 11:47:13

springboot怎么将事务设置为pending,等另外一个请求ok了,再做commit

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
springboot怎么将事务设置为pending,等另外一个请求ok了,再做commit

在Spring Boot中实现跨请求的事务管理是一个复杂的需求,因为HTTP协议是无状态的,而数据库事务通常绑定在一个请求的上下文中。不过,有几种方案可以实现类似的效果:

方案1:使用编程式事务 + 状态存储(推荐)

1.1 手动控制事务边界

@Service public class DistributedTransactionService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private TransactionTemplate transactionTemplate; // 存储事务状态 private Map<String, TransactionStatus> transactionStore = new ConcurrentHashMap<>(); /** * 第一阶段:开始事务并保存状态 */ public String startPendingTransaction() { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = transactionManager.getTransaction(def); String transactionId = UUID.randomUUID().toString(); transactionStore.put(transactionId, status); // 执行业务操作 // yourBusinessLogic(); return transactionId; } /** * 第二阶段:提交事务 */ public void commitTransaction(String transactionId) { TransactionStatus status = transactionStore.get(transactionId); if (status != null) { try { // 执行业务验证 if (validateBusiness()) { transactionManager.commit(status); } else { transactionManager.rollback(status); } } finally { transactionStore.remove(transactionId); } } } /** * 回滚事务 */ public void rollbackTransaction(String transactionId) { TransactionStatus status = transactionStore.get(transactionId); if (status != null) { transactionManager.rollback(status); transactionStore.remove(transactionId); } } }

方案2:使用Saga模式(分布式事务)

2.1 添加依赖

<dependency> <groupId>io.eventuate.tram.sagas</groupId> <artifactId>eventuate-tram-sagas-spring-orchestration-simple-dsl</artifactId> <version>0.21.0.RELEASE</version> </dependency>

2.2 实现Saga协调器

public class TwoPhaseTransactionSaga implements SimpleSaga<TwoPhaseTransactionData> { @Autowired private TransactionService transactionService; @Override public SagaDefinition<SimpleSagaDsl<TwoPhaseTransactionData>, TwoPhaseTransactionData> getSagaDefinition() { return Saga .step() .invokeLocal(this::beginTransaction) .withCompensation(this::rollbackTransaction) .step() .invokeLocal(this::validateAndCommit) .build(); } private void beginTransaction(TwoPhaseTransactionData data) { // 开始事务,但不提交 transactionService.beginPendingTransaction(data.getTransactionId()); } private void validateAndCommit(TwoPhaseTransactionData data) { // 等待其他请求验证 boolean isValid = waitForValidation(data.getTransactionId()); if (isValid) { transactionService.commitTransaction(data.getTransactionId()); } else { throw new RuntimeException("Validation failed"); } } private void rollbackTransaction(TwoPhaseTransactionData data) { transactionService.rollbackTransaction(data.getTransactionId()); } }

方案3:使用数据库SAVEPOINT(适用于同一连接)

@Service public class SavepointTransactionService { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private DataSource dataSource; public void executeWithPendingCommit() { Connection conn = null; Savepoint savepoint = null; try { conn = DataSourceUtils.getConnection(dataSource); conn.setAutoCommit(false); // 关闭自动提交 // 创建保存点 savepoint = conn.setSavepoint("pending_transaction"); // 执行第一阶段操作 jdbcTemplate.update("INSERT INTO table1 ..."); jdbcTemplate.update("UPDATE table2 ..."); // 此时事务未提交,等待其他请求 // 在另一个请求中验证并提交 // validateAndCommit(conn, savepoint); } catch (Exception e) { if (savepoint != null) { conn.rollback(savepoint); } throw new RuntimeException(e); } } /** * 在另一个请求中调用 */ public void validateAndCommit(Connection conn, Savepoint savepoint) { try { // 执行业务验证 boolean isValid = validateBusinessLogic(); if (isValid) { conn.commit(); // 提交事务 } else { conn.rollback(savepoint); // 回滚到保存点 } } catch (Exception e) { throw new RuntimeException(e); } finally { if (conn != null) { try { conn.setAutoCommit(true); conn.close(); } catch (SQLException e) { // 处理异常 } } } } }

方案4:使用消息队列实现最终一致性

@Service public class MessageBasedTransactionService { @Autowired private JmsTemplate jmsTemplate; @Autowired private TransactionalEventPublisher eventPublisher; /** * 第一阶段:发布事件但不提交 */ @Transactional public void phaseOne(String businessData) { // 保存业务数据 businessRepository.save(businessData); // 发布事件(在事务提交后才发送) eventPublisher.publishEvent(new TransactionPendingEvent(businessData)); } /** * 监听事件,执行第二阶段 */ @JmsListener(destination = "transaction.pending") public void handlePendingTransaction(TransactionPendingEvent event) { // 执行业务验证 boolean isValid = validateBusiness(event.getData()); if (isValid) { // 执行提交操作 commitTransaction(event.getTransactionId()); } else { // 执行回滚操作 rollbackTransaction(event.getTransactionId()); } } }

方案5:使用状态机管理事务状态

@Service public class StateMachineTransactionService { public enum TransactionState { PENDING, VALIDATING, COMMITTED, ROLLBACKED } public enum TransactionEvent { VALIDATE, COMMIT, ROLLBACK } @Transactional public String startTransactionWithStateMachine() { String transactionId = UUID.randomUUID().toString(); // 创建状态机 StateMachine<TransactionState, TransactionEvent> stateMachine = stateMachineFactory.getStateMachine(transactionId); // 初始状态为PENDING stateMachine.sendEvent(TransactionEvent.VALIDATE); // 执行业务操作 executeBusinessLogic(); // 返回事务ID供后续查询 return transactionId; } @Transactional public void commitTransaction(String transactionId) { StateMachine<TransactionState, TransactionEvent> stateMachine = stateMachineFactory.getStateMachine(transactionId); if (stateMachine.getState().getId() == TransactionState.VALIDATING) { stateMachine.sendEvent(TransactionEvent.COMMIT); // 执行实际的提交逻辑 executeCommit(); } } }

最佳实践建议

  1. 考虑使用成熟的分布式事务框架

    • Seata

    • Atomikos

    • Narayana

  2. 设计注意事项

    // 1. 设置超时机制 @Transactional(timeout = 300) // 5分钟超时 // 2. 使用异步处理 @Async public CompletableFuture<String> processAsync() { // 异步处理 } // 3. 添加幂等性处理 public void processWithIdempotent(String idempotentKey) { if (processedKeys.contains(idempotentKey)) { return; // 已处理过 } // 执行业务逻辑 processedKeys.add(idempotentKey); }
  3. 清理机制

@Component public class TransactionCleanupScheduler { @Scheduled(fixedDelay = 60000) // 每分钟清理一次 public void cleanupPendingTransactions() { // 清理超时的事务 transactionStore.entrySet().removeIf(entry -> isTransactionTimeout(entry.getValue()) ); } }

注意事项

  1. 事务隔离级别:长时间挂起的事务可能导致锁竞争

  2. 连接池限制:挂起的事务会占用数据库连接

  3. 超时处理:需要设置合理的超时时间

  4. 异常处理:确保异常情况下能正确清理资源

  5. 分布式环境:在集群环境下需要共享事务状态

根据你的具体场景选择最合适的方案,对于简单的需求,方案1(编程式事务)通常足够;对于复杂的分布式场景,建议使用Saga模式或成熟的分布式事务框架。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/5 14:53:19

吐血推荐!专科生毕业论文必备TOP9 AI论文网站

吐血推荐&#xff01;专科生毕业论文必备TOP9 AI论文网站 专科生毕业论文写作的“救星”来了 随着高校教育的不断深化&#xff0c;专科生在毕业论文撰写过程中面临的挑战也日益增多。从选题困难、资料查找繁琐&#xff0c;到格式规范不熟悉、内容质量难以把控&#xff0c;每一个…

作者头像 李华
网站建设 2026/4/10 11:22:20

vivado hls设计总结(二十)

一、硬件高效型C语言代码之C类和模板 1.vivado hls支持C class类的综合 2.vivado hls只是支持对顶层函数进行综合 3.vivado hls不支持对顶层的class类进行综合 4.如果要对类成员函数进行综合&#xff0c;需要将类本身例化为函数 5.不支持对位于顶层的类进行综合 6.不支持对位于…

作者头像 李华
网站建设 2026/4/13 15:14:24

【计算机毕设选题推荐】基于Django+Spark健康风险预测数据可视化分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡如果你遇到具体的…

作者头像 李华
网站建设 2026/4/7 14:50:06

HBase在大数据领域农业数据处理中的应用

HBase在大数据领域农业数据处理中的应用关键词&#xff1a;HBase、农业大数据、分布式存储、实时处理、数据建模、精准农业、智能决策摘要&#xff1a;本文深入探讨HBase在农业大数据处理中的核心应用场景&#xff0c;结合农业数据时空特性、多源异构特征及实时分析需求&#x…

作者头像 李华
网站建设 2026/4/2 10:37:14

DeepSeek V4模型即将来袭,编程能力或将超越GPT与Claude

DeepSeek计划于2月中旬推出主打编程能力的新一代AI模型V4&#xff0c;据内部测试&#xff0c;其在代码相关任务上的表现可能优于Claude和GPT系列。V4在处理超长代码提示方面有新突破&#xff0c;对复杂软件开发者大有帮助。恰逢中国春节发布&#xff0c;网友调侃DeepSeek"…

作者头像 李华
网站建设 2026/4/3 4:51:46

想入行大模型?四大方向详解+系统学习路线,助你快速入门

文章详细解析了AI大模型的四大方向&#xff1a;数据治理、平台搭建、模型算法和部署落地&#xff0c;涵盖工作内容、技能要求和职业前景。强调大模型领域不仅需要算法人才&#xff0c;工程人才同样重要&#xff0c;好的平台和基础设施是产品成功的关键因素。文章建议新人聚焦垂…

作者头像 李华