我想在我的存储库层中有一个选项来预加载实体,所以我尝试添加一个方法来预加载具有所有关系的问题实体,但它会抛出 MultipleBagFetchException。我怎样才能解决这个问题?我正在使用 Hibernate 4.16。
@NamedQuery(name = Question.FIND_BY_ID_EAGER, query = "SELECT q FROM Question q LEFT JOIN FETCH q.answers LEFT JOIN FETCH q.categories LEFT JOIN FETCH q.feedback LEFT JOIN FETCH q.participant WHERE q.id = :id"),
我如何让一个最初是惰性加载的问题对象,以预先加载所有关系?
最佳答案
这是 Hibernate 中的一个相当讨厌的问题,实际上是一般的 ORM。
发生的事情是许多(获取)连接导致创建相当大的笛卡尔积。即在结果中永远加入新列和新行,导致(相当)大的“正方形”结果。
Hibernate 需要从此表中提取图形,但它不够智能,无法将正确的列与正确的实体相匹配。
例如
假设我们有结果
A B C
A B D
需要变成:
A
|
B
/\
C D
Hibernate 可以从主键和一些编码魔术中推断出图形必须是什么,但在实践中它需要明确的帮助才能实现这一点。
一种方法是在关系上指定 Hibernate 特定的 @IndexColumn
或 JPA 标准 @OrderColumn
。
例如
@Entity
public class Question {
@ManyToMany
@JoinTable(
name = "question_to_answer",
joinColumns = @JoinColumn(name = "question_id"),
inverseJoinColumns = @JoinColumn(name = "answer_id")
)
@IndexColumn(name = "answer_order")
private List<Answer> answers;
// ...
}
在这个例子中,我使用了一个连接表,带有一个额外的列 answer_order
。通过这个列,每个问题/答案关系都有一个唯一的序列号,Hibernate 可以区分结果表中的条目并创建所需的对象图。
顺便提一下,如果它涉及多个实体,使用如此多的急切连接可能会导致结果集比您根据所涉及的实体数量想象的要大得多。
进一步阅读:
关于java - Hibernate 抛出的 MultipleBagFetchException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13334831/