使用 JPA 在 Hibernate 中使用 EAGER 类型进行多次提取

Posted

技术标签:

【中文标题】使用 JPA 在 Hibernate 中使用 EAGER 类型进行多次提取【英文标题】:Multiple fetches with EAGER type in Hibernate with JPA 【发布时间】:2013-07-08 03:02:38 【问题描述】:

我有一个实体,其中包含:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "assessment")
@OrderBy(value = "order ASC")
private List<AssessmentPart> assessmentParts = new LinkedList<>();

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "assessment")
private List<AssessmentText> texts = new LinkedList<>();

如您所见,有两个集合需要立即加载。这不起作用,hibernate 会抛出异常:

Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags

这是因为 Hibernate 无法一次性获取多个集合。但是,如果我将 List 更改为 Set 并将 LinkedList 更改为 HashSet 这部分工作正常,但会出现另一个更烦人的问题。

当我尝试使用以下方式从数据库中获取实体时:

entityManager.find(entityClass, primaryKey);

它失败了:

org.hibernate.AssertionFailure: null identifier

我确定我传递给find 方法的 ID 不为空,我已经调试过并且我确信这一点。它以某种方式在 Hibernate 中消失了。

如果我将集合类型更改为LAZY,一切都会正常运行,但在某些情况下我需要使用EAGER

有人有解决方法吗?要么我可以有一个集合但防止发生断言错误,要么我可以有一个列表但以某种方式避免多个 fetch bag 错误。

我正在使用:

Hibernate 4.2.2.Final
Tomcat 7
JPA 2.0
JDK 1.7

编辑

我刚刚发现添加@Fetch(FetchMode.SELECT) 解决了这个问题,我可以使用EAGER 类型的多个列表,但是有没有通过不使用Hibernate 特定的注释来解决这个问题?为什么它首先解决了这个问题?

【问题讨论】:

有一个答案就是这么说的......你应该接受他的回答......只是说。 【参考方案1】:

问题的根本原因在于,当 Hibernate 获取 SQL 查询结果时,没有简单的方法来判断哪个子元素属于哪个集合。请参阅this blog entry 以获取更详细的示例说明。总结一下,您有以下解决方法:

使用子选择 @Fetch(FetchMode.SELECT) 分别加载每个集合 通过添加索引列@IndexColumn(name="LIST_INDEX") 强制使用列表而不是包 使用像 Set 这样的无序集合。

【讨论】:

正如 Hibernate 文档所说 (docs.jboss.org/hibernate/stable/orm/javadocs/org/hibernate/…),@IndexColumn 已被弃用。我建议使用 JPA 的 @OrderColumn (docs.oracle.com/javaee/7/api/javax/persistence/OrderColumn.html)。【参考方案2】:

如果您正在使用 Hibernate 并且您不关心使用 Hibernate 注释:

使用以下方法注释您的集合字段:

@LazyCollection(LazyCollectionOption.FALSE)

记得从@OneToMany 注解中移除 fetchType 属性。

【讨论】:

这是一个特定于休眠的注解

以上是关于使用 JPA 在 Hibernate 中使用 EAGER 类型进行多次提取的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JPA 和 Hibernate 在 UTC 时区中存储日期/时间和时间戳

使用 JPA 在 Hibernate 中使用 EAGER 类型进行多次提取

为啥在 JPA 2/Hibernate 中使用共享主键时实体需要可序列化?

如何在 Hibernate/JPA 中使用 Java 8 Date 库? [复制]

直接加入 JPA 或 HIBERNATE

在 Hibernate/JPA 中,我应该在哪里以及在哪个用例中使用 SessionFactory 和 Session