Query Cache does not support Batch Loading using batch-size
Description
Environment
Attachments
Activity

Fabio Maulo June 5, 2009 at 8:33 PM
Please provide a test case.

Fabio Maulo July 8, 2008 at 7:32 AM
I would like to see a behavior test to understand better if it is a real bug or an expected behavior.
Scheduled to study it more deep in next mayor version.

Winston Fassett February 27, 2008 at 10:45 AM
After spending some more time reviewing SVN logs, I have a simpler fix.
Just change the default value of ManyToOneType's eager field. I was hesitant to do this in the beginning, but now I believe that the current version may have been a mistake.
Here's my rationale:
in revision 2453, justme84 implemented https://nhibernate.jira.com/browse/NH-795#icft=NH-795 - lazy="proxy|false" for associations.
It appears that the whole purpose of this revision was to enable an explicit lazy="proxy" attribute in <many-to-one>
This involved adding an "eager" parameter to SessionImpl.InternalLoad (a method that is only used by AnyType and EntityType for assembling and resolving identifiers)
Before this revision, the default behavior of SessionImpl.InternalLoad was to create proxies for everything (that was nullable).
After this revision:
the eager parameter in SessionImpl.InternalLoad explicitly enables or disables proxy creation
AnyType continues to exhibit the previously default behavior by explicitly specifying eager=false whenever it invokes SessionImpl.InternalLoad
But ManyToOneType effectively reverses the previous default
it passes its eager field to SessionImpl.InternalLoad
But eager will now almost always be true, because ManyToOneType sets lazy=false (and therefore eager=true) in the constructor ManyToOneType(Type persistentClass).
Since that particular constructor is used by NHibernateUtils.Entity() and TypeFactory.ManyToOne(), this effectively propogates the change all over the place.
So, I think this revision accidentally switched the default proxying behavior for ManyToOneType.
It seems to me that NH should always default to returning proxies unless explicitly disabled. It's further supported by the following facts:
The default value for IsLazy in NHibernate.Mapping.ToOne (and therefore OneToOne and ManyToOne) is true
AnyType still defaults to eager=false
So I'm uploading a different patch where I only changed 2 lines of code in 2 files. It also passes all the NH unit tests.
If I get some downtime in my project I'll try to write a test case for the batching stuff.

Winston Fassett February 27, 2008 at 10:18 AM
Ok I've created a patch that appears to solve the problems and also passes all the NH tests.
The patch was derived from this svn path:
https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/tags/1.2.1.GA/nhibernate.
Basically I tweaked the construction of the ManyToOneType in the following places:
QueryTranslator - for cached HQL statements to batch load the returned entities
NHibernate.Tuple.EntityMetamodel - for cached HQL statements with scalar entities to batch load those entities
CriteriaJoinQalker - for cached Criteria queries to batch load the returned entities
NHibernate.Mapping.OneToMany - for cached collections to batch load returned entities

Winston Fassett February 27, 2008 at 8:16 AM
I've confirmed that cached collections have the same problem.
Neither IQuery nor ICriteria implementation uses the batch-loading mechanism. If a batch-size is defined for a class, a cache hit on the query cache will lead to a separate SELECT for each entity cache miss. Have not tried with cached collections.
Originally noted in a forum post here: http://forum.hibernate.org/viewtopic.php?t=983649
It appears to me that the problem is the ManyToOneType that QueryTranslator constructs in RenderSql and RenderScalarSelect and CriteriaJoinWalker constructs in its constructor. It ultimately uses the default constructor of ManyToOneType, which sets eager=true, preventing the query (and the cache) from returning proxies. In the debugger, I flipped it to false, and the batch loading worked great. Not sure if there are broader implications of that changing how the cache implementations create those Types.
I may try to patch it, but was wondering if anyone else had already addressed it. Couldn't find any existing reports related to this issue, so I'm logging it.