I have the following table structure where each line represents a lazy loaded many-to-one collection.
Code:
A
|
B
/ \
C D
If I am navigating my object graph at A, and call A.getBs(), then for each B I call B.getCs() and B.getDs(), I will have executed A * B(A) * C(B) * D(B) queries. This is the worst case scenario and obviously should usually be avoided.
Some optimizations are available to me, namely the eager fetch capability in Hibernate. This gives me:
"from A join fetch A.Bs where A.id = ?"
which will load A and all of its Bs in a single query. So now, I am at, A * C(B) * D(B). And I thought this is where my optimization would stop, but I begain messing around with some other ideas and came across the following optimization.
If I execute the previous fetch, then execute this fetch: ""from A join A.Bs join fetch B.Cs where A.id = ?", I see one additional SQL statement to load all of the Cs. I could do the same to load all of the Ds.
So now the number of SQL statements are A + B + C + D, which I'm very excited about. But there is a catch. When C and D are loaded, they initialize their respective collections on B automatically. This is good. Hibernate basically iterates the result set and for every C or D it finds, it adds them to the collections on B.
The problem is that if B did not have a C or D related to it, the collection on B remains
unititalized. Whenever I then call B.getCs() an SQL call is made to discover that there are no Cs for B.
I understand the problem, but one solution would be to tell the Hibernate collection "you are initialized, and I did the SQL for you so you don't have to do it again."
Is there a way to make the Hibernate collection proxy think it is initialized without making it issue a SQL call?