I have a class that has embedded object
public class A {
@Embedded
private B b;
// getter setter
}
Inside B class, I have a collection e.g.
@Embeddable
public class B {
@OneToMany(fetch=FetchType.LAZY)
@JoinColumn(name="A_ID")
List<C> cList;
}
and class C
@Entity
public class C {
// not important
}
Now I want to query A object using HQL and also retrieve the C list eagerly. I have tried
select a from A a join fetch a.b.c c
but I get this error Join fetch: “query specified join fetching, but the owner of the fetched association was not present in the select list”
I read this Join fetch: "query specified join fetching, but the owner of the fetched association was not present in the select list" and it seems that it is because my collection is stored inside an embedded object.
Of course I can do for loop and utilize Hibernate.initialize
but the performance will drop when more data is being fetched.
Is it possible to do this in HQL at one shot?
It is possible to eager load the embedded collection using HQL. I believe you need to modify you HQL a bit.
I have tested with following entities:
NOTE: Added Multi to your entity names as I already have classes with same name A
, B
and C
in my work space and added @Id
annotation along with toString
method etc.
@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 + "]";
}
}
And finally the HQL used is:
session1.createQuery("select distinct a from MultiA a join fetch a.b.cList").list()
This results in firing the below single SQL using join :
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
and gives the following output that returns 2 entities of MultiA
along with MutliC
populated.
[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]]]]]