Thursday, November 27, 2008

DataExtends to control lazy loading with Hibernate

Who has not suffered from LazyLoadingExceptions with JPA/ Hibernate? Often one uses the open session in view pattern to improve the situation. When sending hibernate-loaded classes over the network, not even this pattern solves the issue.
Thanks to an idea of Michael Vorburger, we have implemented a small abstraction called DataExtent. When loading an object, a DataExtent defines what extent of its "surrounding" object graph we want to load as well.
For this, you 1) define first a data extent, and 2) use it in your findById or findByCriteria methods of the DAO. You would put the often required DataExtents as constants in your DAO, other DataExtents can be defined on the fly.

The following picture illustrates a possible class graph, with different extents we may be interested in:



Sample code:

fileWithoutContentExtent =
new DataExtent(File.class)
.with("name", "lastModified", "fileSize", "mimeType");

fullFileExtent =
new DataExtent(File.class).
with("name", "content", "lastModified", "fileSize", "mimeType");

// The Extent Object of type 'Person'
myExtent = new DataExtent(Person.class);
// Construct a complex graph:
// Person has a List of Teeth, a Tooth has a 'Person' as owner,
// the owner has a list of 'Person' as friends, the friends are again
// the same 'Person'-entity as defined in the beginning.
myExtent.withSubentities(
collection("teeth",
entity(Tooth.class)
.with("owner")
),
collection("friends", myExtent.getRootEntity())
);



Then you can easily control what should be loaded in the DAO (our DAOs are typically a subclass of our generic DAO):
myPerson = myDao.findById(myPk, myExtent); or
myPersonList = myDao.findByCriteria(myCriteria, myExtent);

References: