仅在确定要提交但在提交之前拦截事务
Context是Java – 带有Hibernate和Spring的JPA。
我们来看两阶段提交协议的场景(但只有一个资源):
-
查询从应用程序提交
-
投票是/否(在我们的案例中来自数据库)
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的(*)与@TransactionalEventListener
和TransactionPhase
非常简单,它很好地抽象了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,……)。