OK...so I went and created a test project with just the sample object graph that we have been discussing (full mapping appended at the end of this post).
I then used the following HQL, with SetCacheable(true), and retrieved a single Class1 object from the DB:
Code:
from Class1 where Name = '1'
This is followed by a simple iteration of the Class2List:
Code:
foreach (Class2 class2 in class1.Class2List)
{
}
With SQL Profiler, I see the first SQL statement to get the Class1 object and then a second SQL statement to load the child Class2List. I also notice that the second SQL statement includes an inner join to ClassA and a left outer join to ClassB even though I have not specified fetch="join" anywhere in my mapping.
I then decorate all the relationships with fetch="select" and I start to see a lot more hits to the DB as each relationship is loaded individually.
So, it certainly appears that my previous assumption about many-to-ones being auto join fetched is correct and that fetch="select" is not in fact the default behaviour. Am I missing something?
Another thing I notice is that subsequent HQL calls with the cached query result in no hits to the database at all, even for my one-to-one relationship. This surprised me as I thought I was mirroring the relationships that I have in my real application where I get extra hits to the DB every query. I will have to dig into this further and report back.
Jason
Code:
<class name="Fetching.Domain.Class1, Fetching.Domain" table="Class1">
<cache usage="read-write"/>
<id name="ID" type="Int32" column="ID">
<generator class="identity"/>
</id>
<property name="Name" column="Name" type="String" length="50" not-null="true" />
<set name="Class2List" inverse="true" lazy="true" cascade="all-delete-orphan">
<cache usage="read-write"/>
<key column="Class1ID"/>
<one-to-many class="Fetching.Domain.Class2, Fetching.Domain"/>
</set>
</class>
<class name="Fetching.Domain.Class2, Fetching.Domain" table="Class2">
<cache usage="read-write"/>
<id name="ID" type="Int32" column="ID">
<generator class="identity"/>
</id>
<property name="Name" column="Name" type="String" length="50" not-null="true" />
<many-to-one name="Class1" class="Fetching.Domain.Class1, Fetching.Domain">
<column name="Class1ID" not-null="true" />
</many-to-one>
<many-to-one name="ClassA" class="Fetching.Domain.ClassA, Fetching.Domain">
<column name="ClassAID" not-null="true" />
</many-to-one>
</class>
<class name="Fetching.Domain.ClassA, Fetching.Domain" table="ClassA">
<cache usage="read-write"/>
<id name="ID" type="Int32" column="ID">
<generator class="identity"/>
</id>
<property name="Name" column="Name" type="String" length="50" not-null="true" />
<one-to-one name="ClassB" class="Fetching.Domain.ClassB, Fetching.Domain" cascade="all" />
</class>
<class name="Fetching.Domain.ClassB, Fetching.Domain" table="ClassB">
<cache usage="read-write"/>
<id name="ID" type="Int32" column="ID">
<generator class="foreign">
<param name="property">ClassA</param>
</generator>
</id>
<property name="Name" column="Name" type="String" length="50" not-null="true" />
<one-to-one name="ClassA" class="Fetching.Domain.ClassA, Fetching.Domain" constrained="true" />
</class>