support for deferred constraint (in delete action)
Description
Activity
Show:
Steve Ebersole August 8, 2024 at 2:26 PM
Very few databases actually support deferrable constraints. In fact, PostgreSQL and Oracle are the only 2 I know of. So it does not seem worth the investment to add explicit support for them.
I'd suggest trying `@ForeignKey(..., options="deferrable")` to see if that works for you.
Rejected
Details
Details
Created November 17, 2006 at 11:21 AM
Updated December 3, 2024 at 9:06 AM
Resolved August 8, 2024 at 2:26 PM
Currently Hibernate does not have support for deferred constraints.
In good design usage of deferred constraints can be avoided, but the module which we work on, recieves the data/records/transactions
from other system - and it doesn't keep the proper order of the records in the transaction.
(the problem is also described under: http://forum.hibernate.org/viewtopic.php?t=965663)
Scenario:
Object A has reference to B (unidirectional).
'Normal' delete scenario:
delete A
delete B
The proper order of deleting and all is ok.
Problematic scenario is (one transaction):
delete B
delete A
Of course after first delete (B), database throws an 'foreign' key constraint.
It is easily solvable using deferred contraints - on DB level (Informix/Oracle, etc).
But now Hibernate does a check and throws 'not-null property references a null or transient value'
(in this case B is transient during delete of A).
Looks to me that Hibernate checks to strictly.
Lets analyze this code:
(DefaultDeleteEventListener.java)
protected final void deleteEntity(
final EventSource session,
final Object entity,
final EntityEntry entityEntry,
final boolean isCascadeDeleteEnabled,
final EntityPersister persister)
throws HibernateException {
....
session.getInterceptor().onDelete(
entity,
entityEntry.getId(),
deletedState,
persister.getPropertyNames(),
propTypes
);
// before any callbacks, etc, so subdeletions see that this deletion happened first
persistenceContext.setEntryStatus(entityEntry, Status.DELETED);
EntityKey key = new EntityKey( entityEntry.getId(), persister, session.getEntityMode() );
cascadeBeforeDelete(session, persister, entity, entityEntry);
new ForeignKeys.Nullifier(entity, true, false, session)
.nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
new Nullability(session).checkNullability( entityEntry.getDeletedState(), persister, true );
...
The last three lines does the check which throws an error.
I don't see the reason of this check here - object is just being deleted, so it doesn't matter that some of its
properties is null or transient.
After commenting the code:
// new ForeignKeys.Nullifier(entity, true, false, session)
// .nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
// new Nullability(session).checkNullability( entityEntry.getDeletedState(), persister, true );
the scenario with deferred constraints works properly. Also any side effects wasn't observed.
If it isn't fully correct change, let me know how to improve it.