Hibernate Lightweight Class Wrinkles

Sometimes, in Hibernate, the need arises to load part of an object sometimes, and all of it the rest of the time. In that vein, the Lightweight Class pattern is detailed, allowing you to map both a lightweight version of a class and a heavier version.

Now you may cite the often mentioned issue of whether there is a significant performance difference between a small projection and a select(*). In this case, understand that we have little, if any control over our database schema. In this case, realize that the table has about 80 columns, and for some queries that may return hundreds of results, we really only need 2-5 of these columns. There is a performance difference in this extreme case.

This was all well and good, until we discovered a major issue that was causing our lightweight class not to work when we had both the lightweight and heavyweight versions mapped in a many-to-one relationship to a parent class. The problem is based on the fact that Hibernate uses the table name (not the object name) for uniqueness, so when we eagerly fetched the summary object, Hibernate attempted to resolve the detail object in its session cache. Because the summary object has been loaded, the cache will hit for the detail object, and Hibernate will attempt to put the summary object into the detail field, causing some CGLIB class cast issues.

There are a couple of solutions to this. One is a hack, but effective enough – change the table name for one of the classes to be of a different case (one upper case, one lower case) – the uniqueness is based on a case-sensitive table name, so the session cache won’t it. Alternately, Gavin recommends extending EntityPersister, overriding getIdentifierSpace(), and specifying <class persister=”MyPersister”/>.

Both will work. My additional tips on getting lightweight class to work are here (to be used with the Hibernate documentation on the pattern). It looks like a change in a future version of Hibernate (possibly 2.1.7, certainly 3.0) will make this a non-issue, with uniqueness based on persistent class instead of table name. In the mean time, I hope this is helpful.