Malayalam Favorites

Friday, January 30, 2009

Hibernate Pitfall : Non lazy collection not fully loaded

I recently came across a rather strange problem. I was using hibernate to load a collection eagerly. The collection has the lazy="false" set explicitly, but still I found that while there are 10 associations in the DB, I get only 3. Even more interestingly, once I remove/delete one of the loaded associations, I get the next but still the total count of associations loaded remains the same ! It seemed like hibernate was trying to optimize behind my back by loading only a few of the associated objects rather than the complete set. I had to have a non lazy collection fully loaded in to my domain object since there is no going back to the DB to get the collection.
I played with batch-size, fetching strategies and the like, but most of these don't apply to non-lazy associations. A whole day later I saw the problem...

This post should have been named "Bad developer pitfall", it was a code error on my side. The .equals() and .hashcode() methods were broken, causing many of the returned objects within the collection to be "equivalent" according to the object's own .equals(). Now they are going to be loaded in to a Set; a data structure that by definition does not contain dupes. How does java check for dupes ? by calling the .equals method. Aaahhh it all fits in now. Poor old hibernate was infact loading everything, but as soon as they were being put in to the collection, they were overwriting eachother. Now things would have been even more twisted had I been using these objects as Keys in collections, because as it turned out the hashcode()-equals() contract was intact, but with a broken equals(), you got a broken hashcode() too.

Note to self : think before scribbling out an equals() and hashcode() !