Skip to content

Commit fd52931

Browse files
committed
HHH-19394 recover the functionality of hibernate.unowned_association_transient_check
1 parent acbb9d1 commit fd52931

File tree

3 files changed

+57
-36
lines changed

3 files changed

+57
-36
lines changed

hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import org.hibernate.engine.spi.CollectionEntry;
1717
import org.hibernate.engine.spi.EntityEntry;
1818
import org.hibernate.engine.spi.PersistenceContext;
19-
import org.hibernate.engine.spi.SessionFactoryImplementor;
2019
import org.hibernate.engine.spi.Status;
2120
import org.hibernate.event.spi.DeleteContext;
2221
import org.hibernate.event.spi.EventSource;
@@ -31,13 +30,11 @@
3130
import org.hibernate.type.CompositeType;
3231
import org.hibernate.type.EntityType;
3332
import org.hibernate.type.ForeignKeyDirection;
34-
import org.hibernate.type.ManyToOneType;
3533
import org.hibernate.type.OneToOneType;
3634
import org.hibernate.type.Type;
3735

3836
import static java.util.Collections.EMPTY_LIST;
3937
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
40-
import static org.hibernate.engine.spi.CascadingActions.CHECK_ON_FLUSH;
4138
import static org.hibernate.pretty.MessageHelper.infoString;
4239

4340
/**
@@ -217,11 +214,7 @@ private static <T> void cascadeProperty(
217214

218215
if ( child != null ) {
219216
if ( type instanceof EntityType || type instanceof CollectionType || type instanceof AnyType ) {
220-
final AssociationType associationType = (AssociationType) type;
221-
final boolean unownedTransient = eventSource.getSessionFactory()
222-
.getSessionFactoryOptions()
223-
.isUnownedAssociationTransientCheck();
224-
if ( cascadeAssociationNow( action, cascadePoint, associationType, eventSource.getFactory(), unownedTransient ) ) {
217+
if ( action.cascadeNow( cascadePoint, (AssociationType) type, eventSource.getFactory() ) ) {
225218
cascadeAssociation(
226219
action,
227220
cascadePoint,
@@ -388,33 +381,6 @@ private static boolean isLogicalOneToOne(Type type) {
388381
&& entityType.isLogicalOneToOne();
389382
}
390383

391-
private static boolean cascadeAssociationNow(
392-
CascadingAction<?> action,
393-
CascadePoint cascadePoint,
394-
AssociationType associationType,
395-
SessionFactoryImplementor factory,
396-
boolean unownedTransient) {
397-
return associationType.getForeignKeyDirection().cascadeNow( cascadePoint )
398-
// For check on flush, we should only check unowned associations when strictness is enforced
399-
&& ( action != CHECK_ON_FLUSH || unownedTransient || !isUnownedAssociation( associationType, factory ) );
400-
}
401-
402-
private static boolean isUnownedAssociation(AssociationType associationType, SessionFactoryImplementor factory) {
403-
if ( associationType instanceof ManyToOneType manyToOne ) {
404-
// logical one-to-one + non-null unique key property name indicates unowned
405-
return manyToOne.isLogicalOneToOne() && manyToOne.getRHSUniqueKeyPropertyName() != null;
406-
}
407-
else if ( associationType instanceof OneToOneType oneToOne ) {
408-
// constrained false + non-null unique key property name indicates unowned
409-
return oneToOne.isNullable() && oneToOne.getRHSUniqueKeyPropertyName() != null;
410-
}
411-
else if ( associationType instanceof CollectionType collectionType ) {
412-
// for collections, we can ask the persister if we're on the inverse side
413-
return collectionType.isInverse( factory );
414-
}
415-
return false;
416-
}
417-
418384
private static <T> void cascadeComponent(
419385
final CascadingAction<T> action,
420386
final CascadePoint cascadePoint,

hibernate-core/src/main/java/org/hibernate/engine/spi/CascadingAction.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
import java.util.Iterator;
88

99
import org.hibernate.HibernateException;
10+
import org.hibernate.engine.internal.CascadePoint;
1011
import org.hibernate.event.spi.EventSource;
1112
import org.hibernate.persister.entity.EntityPersister;
13+
import org.hibernate.type.AssociationType;
1214
import org.hibernate.type.CollectionType;
1315
import org.hibernate.type.Type;
1416

@@ -77,4 +79,14 @@ Iterator<?> getCascadableChildrenIterator(
7779
* @since 7
7880
*/
7981
boolean appliesTo(Type type, CascadeStyle style);
82+
83+
/**
84+
* Does this action cascade to the given association at the given {@link CascadePoint}?
85+
*
86+
* @since 7
87+
*/
88+
boolean cascadeNow(
89+
CascadePoint cascadePoint,
90+
AssociationType associationType,
91+
SessionFactoryImplementor factory);
8092
}

hibernate-core/src/main/java/org/hibernate/engine/spi/CascadingActions.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@
1111
import org.hibernate.ReplicationMode;
1212
import org.hibernate.TransientObjectException;
1313
import org.hibernate.collection.spi.PersistentCollection;
14+
import org.hibernate.engine.internal.CascadePoint;
1415
import org.hibernate.event.spi.DeleteContext;
1516
import org.hibernate.event.spi.EventSource;
1617
import org.hibernate.event.spi.MergeContext;
1718
import org.hibernate.event.spi.PersistContext;
1819
import org.hibernate.event.spi.RefreshContext;
1920
import org.hibernate.internal.CoreMessageLogger;
2021
import org.hibernate.persister.entity.EntityPersister;
22+
import org.hibernate.type.AssociationType;
2123
import org.hibernate.type.CollectionType;
24+
import org.hibernate.type.ManyToOneType;
25+
import org.hibernate.type.OneToOneType;
2226
import org.hibernate.type.Type;
2327
import org.jboss.logging.Logger;
2428

@@ -395,7 +399,12 @@ public boolean anythingToCascade(EntityPersister persister) {
395399
// with cascade NONE on all associations
396400
// if the entity has no associations, we can just ignore it
397401
return persister.hasToOnes()
398-
|| persister.hasOwnedCollections();
402+
|| persister.hasOwnedCollections()
403+
// when hibernate.unowned_association_transient_check
404+
// is enabled, we have to check unowned associations
405+
|| persister.hasCollections()
406+
&& persister.getFactory().getSessionFactoryOptions()
407+
.isUnownedAssociationTransientCheck();
399408
}
400409

401410
@Override
@@ -409,6 +418,32 @@ public boolean appliesTo(Type type, CascadeStyle style) {
409418
&& ( type.isComponentType() || type.isAssociationType() );
410419
}
411420

421+
@Override
422+
public boolean cascadeNow(
423+
CascadePoint cascadePoint,
424+
AssociationType associationType,
425+
SessionFactoryImplementor factory) {
426+
return super.cascadeNow( cascadePoint, associationType, factory )
427+
&& ( factory.getSessionFactoryOptions().isUnownedAssociationTransientCheck()
428+
|| !isUnownedAssociation( associationType, factory ) );
429+
}
430+
431+
private static boolean isUnownedAssociation(AssociationType associationType, SessionFactoryImplementor factory) {
432+
if ( associationType instanceof ManyToOneType manyToOne ) {
433+
// logical one-to-one + non-null unique key property name indicates unowned
434+
return manyToOne.isLogicalOneToOne() && manyToOne.getRHSUniqueKeyPropertyName() != null;
435+
}
436+
else if ( associationType instanceof OneToOneType oneToOne ) {
437+
// constrained false + non-null unique key property name indicates unowned
438+
return oneToOne.isNullable() && oneToOne.getRHSUniqueKeyPropertyName() != null;
439+
}
440+
else if ( associationType instanceof CollectionType collectionType ) {
441+
// for collections, we can ask the persister if we're on the inverse side
442+
return collectionType.isInverse( factory );
443+
}
444+
return false;
445+
}
446+
412447
@Override
413448
public boolean deleteOrphans() {
414449
return false;
@@ -507,6 +542,14 @@ public boolean anythingToCascade(EntityPersister persister) {
507542
public boolean appliesTo(Type type, CascadeStyle style) {
508543
return style.doCascade( this );
509544
}
545+
546+
@Override
547+
public boolean cascadeNow(
548+
CascadePoint cascadePoint,
549+
AssociationType associationType,
550+
SessionFactoryImplementor factory) {
551+
return associationType.getForeignKeyDirection().cascadeNow( cascadePoint );
552+
}
510553
}
511554

512555
/**

0 commit comments

Comments
 (0)