仅在确定要提交但在提交之前拦截事务

Context是Java – 带有Hibernate和Spring的JPA。

我们来看两阶段提交协议的场景(但只有一个资源):

  1. 查询从应用程序提交

  2. 投票是/否(在我们的案例中来自数据库)

3.1。 如果是,来自数据库

3.1.1。 ( 在代码中进行回调 ) – 不是协议的一部分

3.1.2。 提交数据库

3.2如果没有

3.2.1回滚到数据库

我想要的是一种在代码中从3.1.1进行回调的方法,但只有当知道事务将被提交但在实际提交之前。 此外,如果在此处抛出exception,则应回滚该事务。

使用Spring的TransactionSynchronization (*),允许您在事务提交/完成之前或提交/完成之后拦截事务。

  • beforeCommit()回调表示在调用方法后仍然可以发生回滚;
  • 即使事务失败,也会调用beforeComplete()
  • 在事务实际提交到数据库之后afterCommit/Complete()并且无法回滚。

现在我看起来似乎我想要的是另一个完整的两阶段提交协议; 但我想知道Spring中是否有解决方法。 区别在于回调中完成的调用无法回滚。

来自Spring 4.2的(*)与@TransactionalEventListenerTransactionPhase非常简单,它很好地抽象了TransactionSynchronization

我只想首先回到一个交易,作为一个工作单元,要么全部通过,要么全部失败。 关于你的方法,你无法回滚,并且需要在交易的开始和结束之间执行,然后我很遗憾地说你没有交易。

你可以在你的方法中做很多检查,以确保回滚的可能性非常小,但是你的方法总是有可能执行并且发生回滚,但是这个机会可能是极其微不足道的,你可能是我很高兴,我不知道。

编辑:我认为类比会很好。

案例1:交易的典型例子是在商店买香蕉,如果你没有钱,或商店没有香蕉,商店没有钱,你没有香蕉,这是正常的发生。 但是如果设置了所有条件,那么事务将成功提交。

案例2:现在你要问的是什么。 为了论证,可以说你是一个小偷,如果你侥幸逃脱,你只想偷香蕉。 你肯定不知道这一点,因为你对未来的询问,除非你是算命先生,当你去偷香蕉时你会被抓住。

如果你回到第一个案例,你可以检查你有钱,商店有香蕉,给你的商店你的钱,把所有的顾客扔出去,锁门到商店,使商店处于不变的状态。 去做你不能回滚的方法,回到商店,拿香蕉。 没有人可以向你保证香蕉仍然存在,但很可能。

您的情况是您的某个资源与两阶段提交(不支持XA )不兼容。 你的想法是朝着XA http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring–with- 的Last Resource Gambit所描述的模式的方向发展的。和不-xa.html

在如何设置Spring Boot + Bitronix +非XA数据源+ XA JMS连接的答案中简要解释了最后一个资源 gambit的使用

顺便说一下,你的问题没有提到你使用的事务管理器的哪个实现(JBossTS,Bitronix JTA,Atomikos Transaction Essentials,……)。