My team has run into an issue programmatically overriding the "lazy" attribute specified in our Hibernate mapping files for collections.
Some background info:
Our application originally used a Versant object database, and we have converted our application to use Hibernate 3.1.3 to persist our data into MySQL 5.1.30-community. We are currently using Java 1.4.2_17 and MySQL connector 3.1.13, but we are moving to the latest of both Java and the MySQL connector in this release cycle. We have gone through great lengths to have no references to Hibernate except in core code, so ALL of our business logic operates on detached objects. Also our application has a client-server architecture, so we frequently send our data objects via RMI to the clients to operate in a separate JVM from the Hibernate persistence context. For these reasons, we map our entities and collections with lazy="false" in most cases.
We have an Equipment class that contains a List collection of children. The children collection is made up of other Equipment objects. This parent-child object tree can be arbitrarily deep, although I believe that 6 or 7 is the deepest that we encounter at this time. Because this tree can be large and most use cases do not require the entire tree, we use lazy="true" for the children collection.
There is a feature in our application that exports Equipment to text. In this case, we always need the entire Equipment parent-child tree and hence we want to perform the retrieves as if children was configured lazy="false". We always query by criteria, so we did what appears to be the most popular answer: Use setFetchMode on the criteria to set it to FetchMode.JOIN. However, this only eagerly fetches the children for the Equipment object being queried. All of the Equipment in the children collection do NOT have their children eagerly fetched. It appears that this change in FetchMode is not applied recursively in order to retrieve the entire Equipment tree.
On the other hand, if we set lazy="false" for the children collection in the mapping file, we find that it does what we want: The entire Equipment tree is retrieved eagerly. This is certainly not the solution we want because as I stated earlier, most of our use cases do not require the entire tree. This creates an unacceptable performance in many areas of our application.
That being said, I see a difference between setting lazy="false" in the mapping file verses setting the FetchMode to EAGER or JOIN. I also find it interesting that you can set the "lazy" attribute and the "fetch" attribute separately in the mapping files. Based on
this article as well as many other sources, these are perpendicular concepts. Lazy determines
what is retrieved, and fetch determines
how to retrieve it. It seems to reason there should be a way to programmatically override lazy="true" to be lazy="false". Furthermore, it appears to me that using FetchMode.JOIN is a workaround to make an association behave as if lazy="false", but only in certain situations.
Does anyone know of the solution to this problem? We really would like to avoid doing any work around, such as writing a method to recursively load the children, as that is not a general solution.
Thanks,
Joe