【问题标题】:Why does Hibernate not support nested transactions outside of Spring?为什么 Hibernate 不支持 Spring 之外的嵌套事务?
【发布时间】:2016-03-15 20:56:02
【问题描述】:

我使用的是 Hibernate4 但不是 Spring。在我正在开发的应用程序中,我想将每个添加、更新、删除的记录记录到单独的日志表中。就目前而言,我的代码按顺序执行两个事务,并且它可以工作,但我真的想将它们包装成一个事务。

我知道 Hibernate 不支持嵌套事务,只能与 Spring 框架结合使用。我读过有关保存点的信息,但它们并不完全相同。

【问题讨论】:

  • 如果不涉及保存点,您对“嵌套事务”的定义是什么?是什么让您认为 Spring 能够以您自己无法使用的方式使用 Hibernate 事务?
  • @JBNizet。从我已经完成的阅读中,如果一个正在使用 Spring 事务,那么如果其中一个操作失败,另一个必须回滚
  • 在 Spring(以及其他任何地方,因为这不是事务的工作方式)中没有这种类型的东西。 Spring 中存在的是简单的事务传播:如果从另一个事务方法调用一个事务方法,那么第二个方法不会启动事务:它在第一个的上下文中执行。但这也是 Hibernate 所做的:docs.jboss.org/hibernate/orm/5.1/javadocs/org/hibernate/…
  • 第二个事务如何“在第一个事务的上下文中执行”?因为如果您已经启动了一个事务并且没有提交也没有回滚,那么您肯定会从 Hiberbate 收到一条错误消息,指出“不支持嵌套事务”?
  • 不,你不会。我不明白你为什么会得到那个。 Spring 永远不会要求 Hibernate 启动嵌套事务。它将看到一个 transactin 已经启动,并且不会尝试启动另一个。与其猜测会发生什么,不如尝试一下,阅读 Spring 文档,如果遇到真正的问题,请使用代码提出具体问题?

标签: spring hibernate transactions nested


【解决方案1】:

关于 JPA 和 JTA 规范的标准中没有任何内容支持嵌套事务。

spring 支持最可能的意思是调用层次结构中多个方法上的@Transactional 注释。 spring 在这种情况下所做的是检查是否存在正在进行的事务,如果没有开始新的事务。

你可能认为下面的情况是嵌套事务。

@Transactional
public void method1(){
    method2(); // method in another class
}

@Transactional(propagation=REQUIRES_NEW)
public void method2(){
    // do something
}

现实中发生的事情简化如下。 transactionManager1transactionManager2 的类型是 javax.transaction.TransactionManager

// call of method1 intercepted by spring
transactionManager1.begin();
// invocation of method1 
// call of method 2 intercepted by spring (requires new detected)
transactionManager1.suspend();
transactionManager2.begin();
// invocation of method2
// method2 finished
transactionManager2.commit();
transactionManager1.resume();
// method1 finished
transactionManager1.commit();

换句话说,一个事务基本上处于暂停状态。理解这一点很重要。由于 transactionManager2 的事务可能看不到 transactionManager1 的变化,具体取决于事务隔离级别。

也许我知道这一点的一点背景。我编写了分布式事务管理系统的原型,允许在云环境中透明地执行方法(一个方法在实例上执行,下一个方法可能在其他地方执行)。

【讨论】:

  • 好的,我从您上面的代码中了解 Spring 所做的事情,但该场景与我试图实现的目标不匹配,即所有影响数据(添加、删除、更新)的操作超过一张桌子要么完全成功,要么完全失败。您描述的场景是两个 trx 交互。我的情况:我不希望某些表受到影响,而另一些则不受影响。抱歉,如果我对问题/问题的描述不清楚。
  • @DJoyce 删除 propagation=REQUIRES_NEW,这就是将会发生的事情。默认为propagation=REQUIREDdocs.spring.io/spring/docs/current/javadoc-api/org/…
  • 你应该在你的算法中添加一个测试,如果事务Manager2失败,transactionManager1不会将他的更改提交到数据库中。但我同意你的介词
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多