rweiser
rweiser

Reputation: 329

Hibernate: Unable to eagerly fetch child collection of a child collection

I have a Session class, which has a mapped collection of Photo objects:

@OneToMany(fetch = FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
@JoinColumn(name = "sessionId", insertable = false, updatable = false)
private SortedSet<Photo> photos = new TreeSet<>();

Each Photo in turn has a collection of Comment objects, which is designated as being FetchType.LAZY (because I don't always want them):

@OneToMany(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
@BatchSize(size=20)
@Fetch(FetchMode.SUBSELECT)
@JoinColumn(name = "photoId", insertable = false, updatable = false)
private SortedSet<Comment> comments = new TreeSet<>();

In my query for Sessions, I'd like to be able to programmatically decide, on-the-fly, whether to include the Comments or not. I've tried (among other variations):

Criteria criteria = hibSession.createCriteria(Session.class, "s")
    .createAlias("photos", "p")
    .setFetchMode("p.comments", FetchMode.JOIN);

But that doesn't do it. Calling photo.getComments() on any of the returned Photo sub-objects throws a LazyInitializationException.

If I (still within the scope of the original Hibernate session) iterate over all the Sessions, and within that all the Photos, and call photo.getComments().size(), that will fetch the Comments (in batches, as specified).

But is there any way to tell the initial query to just eagerly get all the Comments the first time around, without the need to iterate afterwards?

Thanks.

Upvotes: 4

Views: 735

Answers (1)

Maciej Dobrowolski
Maciej Dobrowolski

Reputation: 12122

It's probably well known Hibernate bug HHH-3524, setFetchMode doesn't work as expected in Criteria queries. It was closed as stale issue, but some users report it for Hibernate versions 4.x.x.

To fix that you can use HQL since it works properly:

session.createQuery("SELECT s FROM PhotoSession s " +
    "JOIN FETCH s.photos p " +
    "JOIN FETCH p.comments");

Or use workaround solution with createCriteria(associationPath, JoinType.LEFT_OUTER_JOIN):

Criteria criteria = session.createCriteria(PhotoSession.class, "s");
criteria.createAlias("photos", "p");
criteria.createCriteria("p.comments", "c", JoinType.LEFT_OUTER_JOIN);
criteria.setFetchMode("c", FetchMode.JOIN);

Upvotes: 1

Related Questions