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

use*_*247 33 java tomcat hibernate jpa

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

@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<>();
Run Code Online (Sandbox Code Playgroud)

如你所见,有两个集合需要急切加载.这不起作用,hibernate引发异常:

Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
Run Code Online (Sandbox Code Playgroud)

那是因为Hibernate无法一次性获取多个集合.但是,如果我改变ListSetLinkedListHashSet这部分工作正常,但其他-发生更恼人的问题.

当我试图从数据库中获取实体时使用:

entityManager.find(entityClass, primaryKey);
Run Code Online (Sandbox Code Playgroud)

它失败了:

org.hibernate.AssertionFailure: null identifier
Run Code Online (Sandbox Code Playgroud)

我确信我传递给find方法的ID 不是null,我已经调试过,我确信这一点.它在某种程度上消失在Hibernate内部.

如果我将集合类型更改为LAZY一切正常工作没有错误,但在某些情况下我需要使用EAGER.

有没有人有解决方法如何修复它?要么我可以有一个集,但防止发生断言错误或我可以有一个列表但不知何故避免多个获取包错误.

我在用:

Hibernate 4.2.2.Final
Tomcat 7
JPA 2.0
JDK 1.7
Run Code Online (Sandbox Code Playgroud)

编辑

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

Mak*_*das 60

问题的根本原因是,当Hibernate获取SQL查询结果时,没有简单的方法来判断哪个子元素属于哪个集合.有关示例的详细说明,请参阅此博客条目.总结一下,您有以下解决方法:

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

  • 正如Hibernate文档所述(http://docs.jboss.org/hibernate/stable/orm/javadocs/org/hibernate/annotations/IndexColumn.html),@ IndexColumn已弃用.我建议使用JPA的@ OrderColumn(http://docs.oracle.com/javaee/7/api/javax/persistence/OrderColumn.html). (7认同)

wil*_*ome 15

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

使用以下内容注释您的集合字段:

@LazyCollection(LazyCollectionOption.FALSE)
Run Code Online (Sandbox Code Playgroud)

请记住从@OneToMany批注中删除fetchType属性.

  • 这是一个特定于hibernate的注释 (2认同)