【问题标题】:Hibernate Parent/Child SELECT N+1 issue休眠父/子 SELECT N+1 问题
【发布时间】:2011-03-24 09:54:36
【问题描述】:

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

@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 加载整个表,单个选择会加载所有记录,我可以愉快地遍历树。当我指定检索树上的节点时,我的问题就出现了。我希望节点及其所有子节点都在一次选择中。下面是加载整个表格的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

然后休眠检索节点,但是当我访问子节点时,我得到了 SELECT N+1 问题。我知道为什么会发生这种情况(因为 tree.name = :name),但是有没有办法编写 HQL 以便加载指定的节点及其所有子节点?

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

提前致谢,

【问题讨论】:

    标签: java hibernate tree hql orm


    【解决方案1】:

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

    @BatchSize(size = 20)
    

    例如:

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

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

    【讨论】:

    • 嘿,非常感谢,这确实将性能提高到了可以接受的水平.. 以为我可能必须实现嵌套集,我现在没有时间.. 再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2021-04-26
    • 1970-01-01
    相关资源
    最近更新 更多