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

Context 是 Java - JPA 与 Hibernate 和 Spring。

让我们以两阶段提交协议的场景为例(但仅使用一个资源):

  1. 从应用程序提交查询

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

3.1. 如果是,则来自数据库

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

3.1.2. 提交到数据库

3.2 如果不是

3.2.1 回滚到数据库

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

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

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

现在我看了,似乎我想要的是一个完整的两阶段提交协议中的另一个;但我想知道春季是否有解决方法。不同之处在于,在回调中完成的调用无法回滚。

(*)从Spring 4.2非常简单,它很好地抽象了@TransactionalEventListenerTransactionPhaseTransactionSynchronization


答案 1

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

最后一个资源策略的使用在如何设置Spring Boot + Bitronix + non-XA Datasource + XA JMS Connection的答案中进行了简要说明

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


答案 2

我只想首先回到一个事务,作为一个工作单元,要么全部通过,要么全部失败。关于您的方法,您所说的方法无法回滚,并且需要在事务的开始和结束之间执行,那么我很抱歉地说您没有事务。

你可以在你的方法中做很多检查,以确保回滚的可能性非常小,但是你的方法总是有可能执行并发生回滚,但这种机会可以忽略不计,你可能对此感到满意,我不知道。

编辑:我认为打个比方会很好。

案例1:所以交易的经典例子是在商店买香蕉,如果你没有钱,或者商店没有香蕉,商店没有钱,你没有得到香蕉,这是通常发生的事情。但是,如果设置了所有条件,则事务将成功提交。

案例2:现在,对于您所要求的内容。为了争论,让我们说你是一个小偷,如果你能逃脱,你只想偷香蕉。你不能确切地知道这一点,因为你对未来的询问,除非你是一个算命先生,否则当你去偷香蕉时,你可能会被抓住。

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


推荐