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

时间:2016-08-31 15:25:23

标签: java spring jpa transactions spring-transactions

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

让我们采用两阶段提交协议的方案(但只有一个资源):

  1. 从应用程序提交的查询

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

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

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

    3.1.2。提交数据库

    3.2如果没有

    3.2.1回滚到数据库

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

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

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

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

    来自Spring 4.2的

    (*)非常简单,@TransactionalEventListenerTransactionPhase很好地抽象TransactionSynchronization

2 个答案:

答案 0 :(得分:1)

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

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

修改 我认为类比会很好。

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

案例2:现在问你的问题。为了论证,可以说你是一个小偷,如果你能逃脱它,你只想偷香蕉。你无法确切地知道这一点,因为你对未来的询问,除非你是一个算命先生,当你去偷香蕉时,你可能会被抓住。

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

答案 1 :(得分:1)

您的情况是您的某个资源与两阶段提交不兼容(不是支持XA的)。您的想法是针对{{3>}

XA和最后资源开发 中描述的模式的方向

http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html

的答案中简要解释了最后资源开局的使用

顺便说一句,您的问题并未提及您使用的事务管理器的哪个实现(JBossTS,Bitronix JTA,Atomikos Transaction Essentials,...)。