在具有 JPA 的休眠中使用 EAGER 类型的多个读取

2022-09-01 04:17:33

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

@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<>();

如您所见,有两个集合需要热切地加载。这不起作用,休眠会引发异常:

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

这是因为Hibernate无法一次性获取多个集合。但是,如果我将to和to更改为此部分工作正常,但另一个 - 发生更烦人的问题。ListSetLinkedListHashSet

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

entityManager.find(entityClass, primaryKey);

它失败,因为:

org.hibernate.AssertionFailure: null identifier

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

如果我将集合类型更改为所有内容,则只会正常工作而不会出现错误,但在某些情况下,我需要使用.LAZYEAGER

有没有人有一个解决方案如何解决它?我可以有一个集合,但防止断言错误发生,或者我可以有一个列表,但以某种方式避免多个获取包错误。

我正在使用:

Hibernate 4.2.2.Final
Tomcat 7
JPA 2.0
JDK 1.7

编辑

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


答案 1

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

  • 使用子选择单独加载每个集合@Fetch(FetchMode.SELECT)
  • 通过添加索引列强制使用列表而不是包@IndexColumn(name="LIST_INDEX")
  • 使用无序集合,如 Set。

答案 2

如果您使用的是 Hibernate,并且您不关心使用 Hibernate 注释:

使用以下内容为集合字段添加注释:

@LazyCollection(LazyCollectionOption.FALSE)

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


推荐