Hibernate父/子SELECT N + 1问题

时间:2010-08-02 20:16:24

标签: java hibernate tree hql orm

我给以下映射的超类提供了父/子自我关系的基本实现,以创建一个父/子列表来无限制地嵌套项目(即类别)

@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以便加载指定的节点及其所有子节点?

我只想找到一种方法来支持一个简单的嵌套项目列表,我可以通过一个选择来检索任何父节点及其子节点

提前感谢,

1 个答案:

答案 0 :(得分:1)

您是否尝试过使用@BatchSize注释?

@BatchSize(size = 20)

例如:

@OneToMany(mappedBy = ..., fetch = FetchType.LAZY)
@BatchSize(size = 20)
public SortedSet<Item> getItems() { ... }

然后,如果在HQL中指定对子项的连接,则应该能够避免n + 1选择。我不确定,是否有办法在HQL语句中指定批量大小。