@@ -378,34 +378,16 @@ public void cascade(
378
378
Void context ,
379
379
boolean isCascadeDeleteEnabled )
380
380
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
402
385
// throw new TransientPropertyValueException(
403
386
// "object references an unsaved transient instance - save the transient instance before flushing",
404
387
// entityName,
405
388
// persister.getEntityName(),
406
389
// persister.getPropertyNames()[propertyIndex]
407
390
// );
408
- }
409
391
}
410
392
}
411
393
@@ -443,18 +425,31 @@ public String toString() {
443
425
}
444
426
};
445
427
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!
448
434
return false ;
449
435
}
450
436
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 );
458
453
}
459
454
}
460
455
}
0 commit comments