Skip to content

Commit b2d5bbc

Browse files
committed
HHH-19565 @SQLRestriction should not be applied to a @manytoone
At least not when mapped to a foreign key association. If we apply such a restriction, we will set the FK to null when the entity is updated, resulting in data loss. Note that this was the historical and correct behavior right up until Hibernate 6.2. Some recent tests are asserting a different and dangerous behavior, so I'm changing those tests.
1 parent 0867f68 commit b2d5bbc

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,10 +2091,12 @@ public TableGroupJoin createTableGroupJoin(
20912091
creationState
20922092
) );
20932093

2094+
final EntityMappingType associatedEntityMappingType = getAssociatedEntityMappingType();
2095+
20942096
// Note specifically we only apply `@Filter` restrictions that are applyToLoadByKey = true
20952097
// to make the behavior consistent with lazy loading of an association
2096-
if ( getAssociatedEntityMappingType().getEntityPersister().hasFilterForLoadByKey() ) {
2097-
getAssociatedEntityMappingType().applyBaseRestrictions(
2098+
if ( associatedEntityMappingType.getEntityPersister().hasFilterForLoadByKey() ) {
2099+
associatedEntityMappingType.applyBaseRestrictions(
20982100
join::applyPredicate,
20992101
tableGroup,
21002102
true,
@@ -2104,22 +2106,28 @@ public TableGroupJoin createTableGroupJoin(
21042106
creationState
21052107
);
21062108
}
2107-
getAssociatedEntityMappingType().applyWhereRestrictions(
2108-
join::applyPredicate,
2109-
tableGroup,
2110-
true,
2111-
creationState
2112-
);
2113-
if ( getAssociatedEntityMappingType().getSuperMappingType() != null && !creationState.supportsEntityNameUsage() ) {
2114-
getAssociatedEntityMappingType().applyDiscriminator( null, null, tableGroup, creationState );
2109+
// @SQLRestriction should not be applied when joining FK association,
2110+
// because that would result in us setting the FK to null when the
2111+
// owning entity is updated, that is, to data loss.
2112+
// But we'll let it apply on the TARGET side of a @OneToOne
2113+
if ( sideNature == ForeignKeyDescriptor.Nature.TARGET ) {
2114+
associatedEntityMappingType.applyWhereRestrictions(
2115+
join::applyPredicate,
2116+
tableGroup,
2117+
true,
2118+
creationState
2119+
);
2120+
}
2121+
if ( associatedEntityMappingType.getSuperMappingType() != null && !creationState.supportsEntityNameUsage() ) {
2122+
associatedEntityMappingType.applyDiscriminator( null, null, tableGroup, creationState );
21152123
}
21162124

2117-
final SoftDeleteMapping softDeleteMapping = getAssociatedEntityMappingType().getSoftDeleteMapping();
2125+
final SoftDeleteMapping softDeleteMapping = associatedEntityMappingType.getSoftDeleteMapping();
21182126
if ( softDeleteMapping != null ) {
21192127
// add the restriction
21202128
final TableReference tableReference = lazyTableGroup.resolveTableReference(
21212129
navigablePath,
2122-
getAssociatedEntityMappingType().getSoftDeleteTableDetails().getTableName()
2130+
associatedEntityMappingType.getSoftDeleteTableDetails().getTableName()
21232131
);
21242132
join.applyPredicate( softDeleteMapping.createNonDeletedRestriction(
21252133
tableReference,

hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/join/AttributeJoinWithRestrictedJoinedInheritanceTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ public void testLeftJoinWithDiscriminatorFiltering(SessionFactoryScope scope) {
6666
).getResultList();
6767
assertEquals( 2, resultList.size() );
6868
assertResult( resultList.get( 0 ), 1, 11, 11, "child_a_1", SubChildEntityA1.class );
69-
assertResult( resultList.get( 1 ), 2, 21, null, null, null );
69+
// @SQLRestriction should not be applied when joining FK association
70+
assertResult( resultList.get( 1 ), 2, 21, 21, "child_a_2", SubChildEntityA2.class );
7071
} );
7172
}
7273

hibernate-core/src/test/java/org/hibernate/orm/test/mapping/where/WhereAnnotationAndJoinedInheritanceTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public void testCriteriaQuery(EntityManagerFactoryScope scope) {
7979

8080
// the child
8181
List<PrimaryObject> resultList = entityManager.createQuery( query ).getResultList();
82-
assertThat( resultList.size() ).isEqualTo( 0 );
82+
// @SQLRestriction should not be applied when joining FK association
83+
assertThat( resultList.size() ).isEqualTo( 1 );
8384
}
8485
);
8586
}
@@ -124,7 +125,8 @@ public void testCriteriaQuery2(EntityManagerFactoryScope scope) {
124125
root.get( "child" ).get( "data" ), DELETED_CHILD ) );
125126

126127
List<PrimaryObject> resultList = entityManager.createQuery( query ).getResultList();
127-
assertThat( resultList.size() ).isEqualTo( 0 );
128+
// @SQLRestriction should not be applied when joining FK association
129+
assertThat( resultList.size() ).isEqualTo( 1 );
128130

129131
builder = entityManager.getCriteriaBuilder();
130132
query = builder.createQuery( PrimaryObject.class );

0 commit comments

Comments
 (0)