I found a solution to my original problem by using a slightly different approach. Quoting Hibernate ORM documentation:
Sometimes a proxy or collection needs to be initialized before closing the Session. You can force initialization by calling cat.getSex() or cat.getKittens().size(), for example. However, this can be confusing to readers of the code and it is not convenient for generic code.
The static methods Hibernate.initialize() and Hibernate.isInitialized(), provide the application with a convenient way of working with lazily initialized collections or proxies. Hibernate.initialize(cat) will force the initialization of a proxy, cat, as long as its Session is still open. Hibernate.initialize( cat.getKittens() ) has a similar effect for the collection of kittens.
Simply getting lazy collection (a.getBlist()
) does not make it load - I initially made that mistake. If I try to get some data from that collection (get an item, get collection size) it will load. Calling Hibernate.initialize(..)
on that collection will do the same.
So, iterating over entity associations, and their respective associations, etc, and explicitly initializing them (eg with Hibernate.initialize()
) within session will load everything to be available outside the session once it's closed.
Criteria fetch modes are not used at all with that approach (why won't they work as documented is another question).
It is an obvious case of N+1 problem, but something I can live with.