Reputation: 3166
I have a Hibernate data access layer sitting behind an in-memory object cache. For client side cache misses the in-memory cache will call out to the Hibernate layer to load the object graph into the cache. Due to how objects are serialized into the cache I need to load the entire object graph from Hibernate at one time (i.e. no Lazy loading). A scenario like this is covered in the Hibernate docs here. Here is the excerpt:
In an application with a separate business tier, the business logic must "prepare" all collections that the web tier needs before returning. This means that the business tier should load all the data and return all the data already initialized to the presentation/web tier that is required for a particular use case. Usually, the application calls Hibernate.initialize() for each collection that will be needed in the web tier (this call must occur before the session is closed) or retrieves the collection eagerly using a Hibernate query with a FETCH clause or a FetchMode.JOIN in Criteria. This is usually easier if you adopt the Command pattern instead of a Session Facade.
Since I cannot just enable Eager fetching on my entities directly (I end up with MultipleBagFetchException as documented in this StackOverflow question) I figured I would just keep the default Lazy loading behavior and then perform a Hibernate.initialize()
on each collection in the object so as to fully saturate the object. The problem is that my collections still end up empty.
To further confuse things this strategy seems to be working fine in my unit tests (my objects are saturated properly) but when I run this Hibernate layer as a plugin to my in-memory cache (I'm providing a jar containing my DAL that the in-memory cache will call out to for a cache miss) I'm seeing the behavior described.
Currently I'm handling my session with
<property name="current_session_context_class">thread</property>
and then calling
sessionFactory.getCurrentSession();
in my DAO, after which I do a get on my session for the object to load. As far as I can tell my session handling is the same for both my working unit tests and the non-working DAO. Any suggestions as to what is going on here. If you want more information let me know.
Upvotes: 2
Views: 9723
Reputation: 3166
I found the answer but it's not really related to supposed faulty collection initialization as my OP implies but I'll post it here anyway in hopes that it might help someone:
The problem was that the UUID's (passed as strings throughout the service layer for good reasons that don't matter here) that I'm using to identify objects were being sent in client side in lower case while my (successful) unit tests were sending the UUID string in as upper case. Apparently the DB didn't care about this difference and was able to return at least the root level object of the graph for either case but the subsequent joins to saturate the collections failed given the lower case UUID identifier string of the root level object. Does anyone know why this might be? It looks to me like the Hibernate generated SQL did return the correct results regardless of the case of the UUID but Hibernate ultimately threw out some of the join results because the UUID identifiers didn't technically match.
Upvotes: 1
Reputation: 9255
I've seen this happen sometimes too, and would be curious to know the answer. As a workaround, I've used two different methods to initialize the children:
parent.getChildCollection().size()
Criteria
query with FetchMode.JOIN
on the associationThose seem to always work.
Upvotes: 1