Default FetchMode is Join for many-to-one
Description
Environment
Activity

Alex Zaytsev April 27, 2017 at 10:17 AM
Seems like the same as

stanislav merovic November 4, 2011 at 10:46 AM
this was a hard one (at least for me)
setting use-many-to-one="false" on the filter-def fixed it.

stanislav merovic November 4, 2011 at 10:36 AM
and this seems to be the cause:
enabledFiltersForManyToOne.Count = 1, although there is no filter for the manytoone but for the list/one-to-many.
JoinWalker -> MergeOuterJoins:
// NH Different behavior : NH1179 and NH1293
// Apply filters in Many-To-One association
if (enabledFiltersForManyToOne.Count > 0)
{
string manyToOneFilterFragment = oj.Joinable.FilterFragment(oj.RHSAlias, enabledFiltersForManyToOne);
bool joinClauseDoesNotContainsFilterAlready =
outerjoin.ToFromFragmentString.IndexOfCaseInsensitive(manyToOneFilterFragment) == -1;
if (joinClauseDoesNotContainsFilterAlready)
{
outerjoin.AddCondition(manyToOneFilterFragment);
}
}

stanislav merovic November 4, 2011 at 9:24 AM
ok its not "that" easy...
what causes this behaviour is a filter inside a collection.
<class name="A">
<many-to-one name="B" />
<many-to-one name="C1" />
<list name="ListOfD" cascade="all-delete-orphan" lazy="false">
<key column="itemid"/>
<index column="itemdetailindex"/>
<one-to-many class="D"/>
<filter name="FilterForD" condition="arameter<=somevalue OR somevalue IS NULL"/>
</list>
...
</class>
activating the filter will produce the sql as described above.

stanislav merovic November 4, 2011 at 7:14 AM
turns out that the default has been join before too BUT in 3.2 the where clause for the many-to-one's is included which means that the left outer joins actually become inner joins.
having a where defined in the mapping for the many-to-one entity or using subclassing with discriminators will generate those where-clauses.
<class name="A">
<many-to-one name="B" />
<many-to-one name="C1" />
</class>
<class name="B" where="somefield=1">
</class>
<class name="C" abstract="true">
<discriminator column="type" type="String"/>
<subclass name="C1" discriminator-value="test"/>
</class>
will result in a query like:
select fields from A
left outer join B on A.refB = B.id
left outer join C1 on A.refC = C1.id
where B.somefield = 1 and C1.type = 'test'
so having null values in one of those references will actually end up with no results beeing returned.
Details
Details
Assignee

Reporter

Documentation states that the default for fetch is select but it is join.
That's a change we just struggled with when upgrading to 3.2. Not sure so if it is intended or a bug.