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
仅当您需要在 where
或 select
子句中直接使用别名,以及需要对 c
的属性进行某些连接时才需要别名 class.
可以使用 HQL 预先加载嵌入式集合。我相信你需要稍微修改一下你的HQL。
我已经对以下实体进行了测试:
注意: 添加 Multi 到你的实体名称,因为我已经有 类 同名 A
,B
和 C
在我的工作 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]]]]]
我有一个 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
仅当您需要在 where
或 select
子句中直接使用别名,以及需要对 c
的属性进行某些连接时才需要别名 class.
可以使用 HQL 预先加载嵌入式集合。我相信你需要稍微修改一下你的HQL。
我已经对以下实体进行了测试:
注意: 添加 Multi 到你的实体名称,因为我已经有 类 同名 A
,B
和 C
在我的工作 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]]]]]