This seems to be a very fundamental scenario to me but I cannot find an answer anywhere.
I have three entities. A Parent entity that has a one-to-many association to Child entities and the Child entity has a one-to-many assocation with GrandChild entities.
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Parent_ID", nullable = false)
private Integer id;
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade =CascadeType.ALL, orphanRemoval = true)
private Set<Child> children;
}
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Child_ID", nullable = false)
private Integer id;
@ManyToOne
@JoinColumn(name = "Parent_ID")
private Parent parent;
@OneToMany(mappedBy = "child", fetch = FetchType.LAZY, cascade =CascadeType.ALL, orphanRemoval = true)
private Set<GrandChild> grandChildren;
}
public class GrandChild {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "GrandChild_ID", nullable = false)
private Integer id;
@ManyToOne
@JoinColumn(name = "Child_ID")
private Child child;
}
Using the code below I get a HibernateException: collection evicted error. I assume this is because it has retrieved multiple rows from the database and is trying to return a collection instead of just one Parent record with multiple children where each child has multiple grandchildren, which is what I want. What am I doing wrong? Or is my expectation incorrect?
public Parent test(Integer id) {
CriteriaBuilder criteriaBuilder = this.getSession().getCriteriaBuilder();
CriteriaQuery<Parent> criteriaQuery = criteriaBuilder.createQuery(Parent.class);
Root<Parent> parent = criteriaQuery.from(Parent.class);
Fetch<Parent , Child> childFetch = parent .fetch("children", JoinType.LEFT);
Fetch<Child, GrandChild> grandChildFetch = childFetch.fetch("grandChildren", JoinType.LEFT);
criteriaQuery.where(criteriaBuilder.equal(parent.get("id"), id));
return this.getSession().createQuery(criteriaQuery).getSingleResult();
}