我给以下映射的超类提供了父/子自我关系的基本实现,以创建一个父/子列表来无限制地嵌套项目(即类别)
@MappedSuperclass
public abstract class ParentChildPathEntity<N extends ParentChild> implements MaterializedPath<N> {
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "parent_id")
private N parent;
@Column(name = "name", unique = true)
private String name;
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<N> children = new HashSet<N>();
如果我在父项和子项上使用fetch join加载整个表,则单个select会加载所有记录,我可以愉快地遍历树。当我指定检索树上的节点时,我的问题就出现了。我希望节点及其所有子节点在一个选择中。下面是用于加载整个表的hql:
hql.append(String.format("tree from %s tree ", tableName));
hql.append("left join fetch tree.parent ");
hql.append("left join fetch tree.children ");
如果我指定节点名称,即:
where tree.name = :name
然后hibernate检索节点,但当我访问孩子时,我得到SELECT N + 1问题。我知道为什么会发生这种情况,(因为tree.name =:name)但是有没有办法编写HQL以便加载指定的节点及其所有子节点?
我只想找到一种方法来支持一个简单的嵌套项目列表,我可以通过一个选择来检索任何父节点及其子节点
提前感谢,
答案 0 :(得分:1)
您是否尝试过使用@BatchSize注释?
@BatchSize(size = 20)
例如:
@OneToMany(mappedBy = ..., fetch = FetchType.LAZY)
@BatchSize(size = 20)
public SortedSet<Item> getItems() { ... }
然后,如果在HQL中指定对子项的连接,则应该能够避免n + 1选择。我不确定,是否有办法在HQL语句中指定批量大小。