Skip to content

Commit 8686392

Browse files
committed
clean up logic in CHECK_ON_FLUSH
so that it's more readable/understandable Signed-off-by: Gavin King <[email protected]>
1 parent 6f58c5e commit 8686392

File tree

2 files changed

+28
-32
lines changed

2 files changed

+28
-32
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.hibernate.engine.internal;
88

9+
import org.checkerframework.checker.nullness.qual.Nullable;
910
import org.hibernate.HibernateException;
1011
import org.hibernate.TransientObjectException;
1112
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
@@ -296,7 +297,7 @@ public static boolean isNotTransient(
296297
* @return {@code true} if the given entity is transient (unsaved)
297298
*/
298299
public static boolean isTransient(
299-
String entityName, Object entity, Boolean assumed, SharedSessionContractImplementor session) {
300+
String entityName, Object entity, @Nullable Boolean assumed, SharedSessionContractImplementor session) {
300301
if ( entity == UNFETCHED_PROPERTY ) {
301302
// an unfetched association can only point to
302303
// an entity that already exists in the db

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

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -378,34 +378,16 @@ public void cascade(
378378
Void context,
379379
boolean isCascadeDeleteEnabled)
380380
throws HibernateException {
381-
if ( child != null
382-
// a proxy is always non-transient
383-
// and ForeignKeys.isTransient()
384-
// is not written to expect a proxy
385-
&& !isHibernateProxy( child ) ) {
386-
// if it's associated with the session
387-
// we are good, even if it's not yet
388-
// inserted, since ordering problems
389-
// are detected and handled elsewhere
390-
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( child );
391-
if ( !isInManagedState( entry )
392-
// TODO: check if it is a merged entity which has not yet been flushed
393-
// Currently this throws if you directly reference a new transient
394-
// instance after a call to merge() that results in its managed copy
395-
// being scheduled for insertion, if the insert has not yet occurred.
396-
// This is not terrible: it's more correct to "swap" the reference to
397-
// point to the managed instance, but it's probably too heavy-handed.
398-
&& ( entry != null && entry.getStatus() == Status.DELETED || isTransient( entityName, child, null, session ) ) ) {
399-
throw new TransientObjectException( "persistent instance references an unsaved transient instance of '" +
400-
entityName + "' (save the transient instance before flushing)" );
401-
//TODO: should be TransientPropertyValueException
381+
if ( child != null && isChildTransient( session, child, entityName ) ) {
382+
throw new TransientObjectException( "persistent instance references an unsaved transient instance of '"
383+
+ entityName + "' (save the transient instance before flushing)" );
384+
//TODO: should be TransientPropertyValueException
402385
// throw new TransientPropertyValueException(
403386
// "object references an unsaved transient instance - save the transient instance before flushing",
404387
// entityName,
405388
// persister.getEntityName(),
406389
// persister.getPropertyNames()[propertyIndex]
407390
// );
408-
}
409391
}
410392
}
411393

@@ -443,18 +425,31 @@ public String toString() {
443425
}
444426
};
445427

446-
private static boolean isInManagedState(EntityEntry entry) {
447-
if ( entry == null ) {
428+
private static boolean isChildTransient(EventSource session, Object child, String entityName) {
429+
if ( isHibernateProxy( child ) ) {
430+
// a proxy is always non-transient
431+
// and ForeignKeys.isTransient()
432+
// is not written to expect a proxy
433+
// TODO: but the proxied entity might have been deleted!
448434
return false;
449435
}
450436
else {
451-
switch ( entry.getStatus() ) {
452-
case MANAGED:
453-
case READ_ONLY:
454-
case SAVING:
455-
return true;
456-
default:
457-
return false;
437+
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( child );
438+
if ( entry != null ) {
439+
// if it's associated with the session
440+
// we are good, even if it's not yet
441+
// inserted, since ordering problems
442+
// are detected and handled elsewhere
443+
return entry.getStatus().isDeletedOrGone();
444+
}
445+
else {
446+
// TODO: check if it is a merged entity which has not yet been flushed
447+
// Currently this throws if you directly reference a new transient
448+
// instance after a call to merge() that results in its managed copy
449+
// being scheduled for insertion, if the insert has not yet occurred.
450+
// This is not terrible: it's more correct to "swap" the reference to
451+
// point to the managed instance, but it's probably too heavy-handed.
452+
return isTransient( entityName, child, null, session );
458453
}
459454
}
460455
}

0 commit comments

Comments
 (0)