不使用事务、传播支持和 OpenEntityManager 模式的 JPA 行为不一致

Posted

技术标签:

【中文标题】不使用事务、传播支持和 OpenEntityManager 模式的 JPA 行为不一致【英文标题】:Inconsistent JPA behavior using no transaction, propagation SUPPORTS and OpenEntityManager pattern 【发布时间】:2015-02-05 10:59:40 【问题描述】:

我们使用 JPA (Hibernate 4) 和 Spring 4 管理 JTA 事务。为了在没有任何事务的情况下简单地从数据库中读取时也允许延迟初始化,我们添加了“OpenEntityManager”模式。

您可以在 GitHub https://github.com/abenneke/sandbox/tree/master/spring-hibernate4-transaction 上找到这些问题的测试用例

我们知道完全没有事务同步和支持同步是有区别的。但是 JPA 的行为似乎在某种程度上不一致:

如果没有活动的事务同步,当尝试使用 JPA 持久化某些内容时,我们会从 Springs SharedEntityManagerCreator 收到 TransactionRequiredException。 如果只有一个 SUPPORTS 事务同步处于活动状态,我们不会收到此异常,并且持久请求会被静默忽略。然而,这正是在创建上述异常时在 SharedEntityManagerCreator 中要避免的情况。 如果“OpenEntityManager”模式处于活动状态,也不例外,并且持久请求也会被静默忽略。

在我看来,这些情况之间没有真正的区别,我希望在所有情况下都会看到这种异常,还是没有?

谢谢!

2015 年 7 月更新:我现在将此作为问题提交给 Spring https://jira.spring.io/browse/SPR-13243

【问题讨论】:

【参考方案1】:

见:

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html

(OpenEntityManagerInViewFilter 应该以同样的方式工作)

注意:默认情况下,此过滤器不会刷新 Hibernate 会话, 冲洗模式设置为 FlushMode.NEVER。它假定用于 与关心的服务层事务相结合 flushing:活动事务管理器将临时更改 在读写事务期间刷新模式到 FlushMode.AUTO,使用 在每个事务结束时刷新模式重置为 FlushMode.NEVER。 如果 您打算在没有事务的情况下使用此过滤器,请考虑更改 默认刷新模式(通过“flushMode”属性)。

因此,使用 OEMIV 并且没有事务没有 Flush,因此没有 TransactionRequiredException。

【讨论】:

感谢您的提示,但是 JPA/EntityManagers 只知道两种刷新模式:AUTO 和 COMMIT。并且 Springs SharedEntityManagerCreator 不考虑任何此类模式,并且只要没有事务性 EntityManager 实例可用,就会抛出异常。所以我不认为这是一个解决方案......?

以上是关于不使用事务、传播支持和 OpenEntityManager 模式的 JPA 行为不一致的主要内容,如果未能解决你的问题,请参考以下文章

事务的传播机制

事务的传播机制

java面试题Spring支持的常用事务传播属性和事务传播级别

JPA常用的关闭流的方式是啥?事务管理?还是手动关闭?

spring的不同事务传播行为和用途。

Spring支持的常用数据库事务传播属性和隔离级别