@@ -1557,7 +1557,19 @@ public static class EntityB {
15571557
15581558 having the left join we don't want to add an extra implicit join that will be translated into an SQL inner join (see HHH-15342)
15591559 */
1560- if ( fetchTiming == FetchTiming .IMMEDIATE && selected ) {
1560+
1561+ final ForeignKeyDescriptor .Nature resolvingKeySideOfForeignKey = creationState .getCurrentlyResolvingForeignKeyPart ();
1562+ final ForeignKeyDescriptor .Nature side ;
1563+ if ( resolvingKeySideOfForeignKey == ForeignKeyDescriptor .Nature .KEY && this .sideNature == ForeignKeyDescriptor .Nature .TARGET ) {
1564+ // If we are currently resolving the key part of a foreign key we do not want to add joins.
1565+ // So if the lhs of this association is the target of the FK, we have to use the KEY part to avoid a join
1566+ side = ForeignKeyDescriptor .Nature .KEY ;
1567+ }
1568+ else {
1569+ side = this .sideNature ;
1570+ }
1571+
1572+ if ( ( fetchTiming == FetchTiming .IMMEDIATE && selected ) || needsJoinFetch ( side ) ) {
15611573 final TableGroup tableGroup = determineTableGroupForFetch (
15621574 fetchablePath ,
15631575 fetchParent ,
@@ -1635,16 +1647,6 @@ else if ( hasNotFoundAction()
16351647
16361648 */
16371649
1638- final ForeignKeyDescriptor .Nature resolvingKeySideOfForeignKey = creationState .getCurrentlyResolvingForeignKeyPart ();
1639- final ForeignKeyDescriptor .Nature side ;
1640- if ( resolvingKeySideOfForeignKey == ForeignKeyDescriptor .Nature .KEY && this .sideNature == ForeignKeyDescriptor .Nature .TARGET ) {
1641- // If we are currently resolving the key part of a foreign key we do not want to add joins.
1642- // So if the lhs of this association is the target of the FK, we have to use the KEY part to avoid a join
1643- side = ForeignKeyDescriptor .Nature .KEY ;
1644- }
1645- else {
1646- side = this .sideNature ;
1647- }
16481650 final DomainResult <?> keyResult ;
16491651 if ( side == ForeignKeyDescriptor .Nature .KEY ) {
16501652 final TableGroup tableGroup = sideNature == ForeignKeyDescriptor .Nature .KEY
@@ -1696,6 +1698,22 @@ else if ( hasNotFoundAction()
16961698 );
16971699 }
16981700
1701+ private boolean needsJoinFetch (ForeignKeyDescriptor .Nature side ) {
1702+ if ( side == ForeignKeyDescriptor .Nature .TARGET ) {
1703+ // The target model part doesn't correspond to the identifier of the target entity mapping
1704+ // so we must eagerly fetch with a join (subselect would still cause problems).
1705+ final EntityIdentifierMapping identifier = entityMappingType .getIdentifierMapping ();
1706+ final ValuedModelPart targetPart = foreignKeyDescriptor .getTargetPart ();
1707+ if ( identifier != targetPart ) {
1708+ // If the identifier and the target part of the same class, we can preserve laziness as deferred loading will still work
1709+ return identifier .getExpressibleJavaType ().getJavaTypeClass () != targetPart .getExpressibleJavaType ()
1710+ .getJavaTypeClass ();
1711+ }
1712+ }
1713+
1714+ return false ;
1715+ }
1716+
16991717 private boolean isAffectedByEnabledFilters (DomainResultCreationState creationState ) {
17001718 final LoadQueryInfluencers loadQueryInfluencers = creationState .getSqlAstCreationState ()
17011719 .getLoadQueryInfluencers ();
0 commit comments