It’s painfully obvious how to lazily load collections in Hibernate. Simply set lazy=”true” and you’re ready to go. Doing the same for associated objects can be a bit more intimidating. The use of the term “proxy”, and no sign of the familiar lazy loading terminology can be a bit intimidating, but it really is just as trivial.
It’s not as intuitive because it’s accomplished indirectly. You actually have to change the related object rather than changing the relationship. Suppose we have a Cat object (the preferred object of Hibernate documentation), and each Cat has an Owner class associated with it via a many-to-one relationship. To ensure that the Owner is lazily loaded, we simply change the definition of the mapping of the Owner class, adding proxy=”net.sf.hibernate.Owner”. Now, any class that has a 1-1 or N-1 relationship to an Owner will default to lazily-loading the Owner object.
In practice, the proxy functionality allows so much more than this, but for a quick solution, it works like a charm. Especially interesting is how Hibernate uses CGLib to create the proxy interface for the class on-the-fly. It appears to create a wrapper class around your object that extends each method to first check for the initialization of the object, and then, if/when initialized, returns the expected result.
One gotcha here is that specifying a proxy makes lazy loading the default behavior for all relationships. To override this, I believe an “outer join fetch” is needed in an HQL query. Still, this sort of strategy is used when tuning an application, so outer join fetches and such are a necessary evil(?) anyhow.
You don’t need HQL (just if you want runtime override), declare the as outer-join=”true” if you don’t want lazy loading.
the “many-to-one”
Right, good point, Christian. outer-join=”true” is very useful in defining default behavior for non-HQL queries. HQL is a nice way to allow finely tuned behavior – the more I work with it, the more I respect it. (good work)
I’ve been so buried in HQL land, I sometimes forget to comment on the non-HQL approach. If a developer is already using an HQL query, and using a bad session management pattern (session-per-query or something), they could unintentionally be dependent on the (non-proxy) existing Hibernate behavior where it auto-loads the Owner object. This change would cause their app to flip out when Hibernate tries to lazy-load, but the session is already closed. At this point, it would be best if they were introduced to open-session-in-view, but I thought I’d at least throw a bone to developers who might try this and get unexpected results. Sounds contrived, but I’ve seen it, so I thought I’d mention it.
Hey dudes, also you can just call Hibernate.initialize on the collection giving you trouble. Just do it before you close the session, and you be set!