@@ -1557,7 +1557,19 @@ public static class EntityB {
1557
1557
1558
1558
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)
1559
1559
*/
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 ) ) {
1561
1573
final TableGroup tableGroup = determineTableGroupForFetch (
1562
1574
fetchablePath ,
1563
1575
fetchParent ,
@@ -1635,16 +1647,6 @@ else if ( hasNotFoundAction()
1635
1647
1636
1648
*/
1637
1649
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
- }
1648
1650
final DomainResult <?> keyResult ;
1649
1651
if ( side == ForeignKeyDescriptor .Nature .KEY ) {
1650
1652
final TableGroup tableGroup = sideNature == ForeignKeyDescriptor .Nature .KEY
@@ -1696,6 +1698,22 @@ else if ( hasNotFoundAction()
1696
1698
);
1697
1699
}
1698
1700
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
+
1699
1717
private boolean isAffectedByEnabledFilters (DomainResultCreationState creationState ) {
1700
1718
final LoadQueryInfluencers loadQueryInfluencers = creationState .getSqlAstCreationState ()
1701
1719
.getLoadQueryInfluencers ();
0 commit comments