Hibernate HQL eager load collection in embedded object

Hibernate HQL eager load collection in embedded object

我有一个 class 嵌入了 object

public class A {
   @Embedded
   private B b;

   // getter setter
}

在 B class 里面,我有一个 collection 例如

@Embeddable
public class B {
    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumn(name="A_ID")
    List<C> cList;
}

和class C

@Entity
public class C {
    // not important
}

现在我想用HQL 查询A object 并且急切地检索C 列表。我试过了

select a from A a join fetch a.b.c c

但是我得到这个错误Join fetch: “query specified join fetching, but the owner of the fetched association was not present in the select list”

我读了这个 Join fetch: "query specified join fetching, but the owner of the fetched association was not present in the select list" 似乎是因为我的 collection 存储在嵌入式 object 中。

当然我可以做for循环并利用Hibernate.initialize但是当获取更多数据时性能会下降。

是否可以在 HQL 中一次做到这一点?

尝试在 HQL 中删除 c 的别名,如下所示:

select a from A a join fetch a.b.c

仅当您需要在 whereselect 子句中直接使用别名,以及需要对 c 的属性进行某些连接时才需要别名 class.

可以使用 HQL 预先加载嵌入式集合。我相信你需要稍微修改一下你的HQL。

我已经对以下实体进行了测试:

注意: 添加 Multi 到你的实体名称,因为我已经有 类 同名 ABC 在我的工作 space 中添加了 @Id 注释以及 toString 方法等

@Entity
class MultiA {
    public MultiA() {}

    public MultiA(List<MultiC> cList) {
        this.b.cList = cList;
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int id;
    @Embedded

    public MultiB b = new MultiB();
    @Override
    public String toString() {
        return "MultiA [id=" + id + ", b=" + b + "]";
    }

}

@Embeddable
class MultiB {
    @OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinColumn(name="A_ID")
    List<MultiC> cList = new ArrayList<MultiC>();

    @Override
    public String toString() {
        return "MultiB [cList=" + cList + "]";
    }

}

@Entity
class MultiC {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int id;

    @Override
    public String toString() {
        return "MultiC [id=" + id + "]";
    }
}

最后使用的HQL是:

session1.createQuery("select distinct a from MultiA a join fetch a.b.cList").list()

这会导致使用 join 触发下面的单个 SQL:

Hibernate: select distinct multia0_.id as id1_0_0_, clist1_.id as id1_1_1_, clist1_.A_ID as A_ID2_1_0__, clist1_.id as id1_1_0__ from MultiA multia0_ inner join MultiC clist1_ on multia0_.id=clist1_.A_ID

并给出以下输出,其中 returns 2 个 MultiA 实体以及 MutliC 已填充。

[MultiA [id=1, b=MultiB [cList=[MultiC [id=1], MultiC [id=2], MultiC [id=3]]]], 
MultiA [id=2, b=MultiB [cList=[MultiC [id=6], MultiC [id=4], MultiC [id=5]]]]]