EJB Transactions属性:NOT_SUPPORTED和REQUIRES_NEW

时间:2015-02-05 03:31:02

标签: java hibernate java-ee jpa transactions

我目前陷入以下情况:

我正在尝试将对象A保存到数据库中。但A由许多其他对象组成,B,C和B,C由对象D,E组成......有很多嵌套对象,你知道我的意思。让我们调用将A保存为事务1的整个过程。

在事务1的中间,当涉及保存一些对象X(通过多个链接与A有些关联)时,让我们说它是触发保存X的方法saveX()。在saveX()方法中,业务逻辑需要对另一个对象Y执行另一个查询,让我们说该方法是queryY()。

因此,当我们调用queryY()时,当它转到实际从数据库获取所有结果的代码行时,我们有一个例外。让我们把这个时刻称为T时间。

例外是

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: A.b -> B.

所以我认为,EJB容器在T时有点想,当我们需要进行查询时,它需要提交当前事务1并启动事务2来执行查询。显然,与A相关的数据尚未正确保存到数据库中,因此会发生异常。

所以我们需要暂停事务1并在我们执行查询后重新启动它,而不是在T时间提交它。我做了一些研究,发现@TransactionAttribute可以解决问题。有趣的是,如果我将这两个中的一个放在queryY()上作为注释,我发现下面的两个解决方案都起作用(没有异常发生并且应用程序没问题):

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 

我阅读了与传单有关的官方文档:http://docs.oracle.com/javaee/6/api/javax/ejb/TransactionAttributeType.html

REQUIRES_NEW有效是有道理的。但我不明白为什么NOT_SUPPORTED也能正常工作。显然我们需要另一个事务来调用queryY()来完成查询。在NOT_SUPPORTED的解释中,它没有提到它会在暂停第一个事务后启动一个新事务。

所以我的第一个问题是,为什么NOT_SUPPORTED有效? 我的第二个问题是,为什么EJB容器认为事务1已经结束并且需要在T时提交而不是将queryY作为事务1的一部分?

提前致谢!任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

这与事务传播无关。您应该使用一个且仅一个事务来保存所有对象。

您收到此错误:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: A.b -> B.

是因为你试图保存A而且A和B之间没有级联。

如果A是父,B是子(具有FK),则将持久/合并操作从A级联到B是有意义的。否则,如果B是父@OneToOne关联,则需要先保存它。