I am experiencing the following clearly undocumented problem, and I want to understand if
- Did I do something wrong.
- Has anyone encountered the same problem?
- Is this not documented at all? or am I missing something?
Behavior is Suppose the following mapping
<class name="org.sample.Foo" table="foo"> ... <many-to-one name="bar" class="org.sample.Bar"/> </class> <class name="org.sample.Bar" table="bar" lazy="false"> ... </class>
Firstly, as the background, the default Hibernate for the fetch attribute for the many-to-one relationship should be βselectβ, this is at least what is documented (I will add the link here when I find it)
However, this, apparently, is true only if the reference class lazy = "true"!
therefore, obviously, the conversion above translates to this (since Bar is lazy = "false"):
<class name="org.sample.Foo" table="foo"> ... <many-to-one name="bar" class="org.sample.Bar" *fetch="join" /> </class> <class name="org.sample.Bar" table="bar" lazy="false"> ... </class>
Now why is this going to be a problem? instead of 2 selects, Hibernate will load an awkward link in one element with its "parent" (load Foo with Bar in one choice)
it really makes sense since the object is not lazy, why not load it?
The answer is: what happens if Bar is in the second-level cache?
<class name="org.sample.Foo" table="foo"> ... <many-to-one name="bar" class="org.sample.Bar" *fetch="join" /> </class> <class name="org.sample.Bar" table="bar" lazy="false"> <cache usage="transactional" /> ... </class>
And the answer to this question is that nothing is changing!
Apparently, it is assumed that Hibernate is smart enough to understand that objects of this type should not load, but since the default choice was changed from select to join, Hibernate has no choice (you cannot join a real table with a second-level cache , till)
therefore, Hibernate does what it is told, and uses a connection to retrieve the object from the database, where it is already in the second level cache
The solution I found is to literally change the display to fetch = "select"
Now that the second choice for the bar is ready, Hibernate realizes that it should not go to the database and retrieve it from the cache. and only 1 request will be executed (after warming up)