I have problem with deletion:
Scenario:
Object A has reference to B (unidirectional).
'Normal' delete scenario:
delete A
delete B
The proper order of deleting and all is ok.
But external system, which sends a lot of transactions to our system, doesn't care about order of records in transactions.
So the problematic scenario is (one transaction):
delete B
delete A
Of course after first delete (B), database throws an 'foreign' key contraint.
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).
Also I didn't find any remark in documentation / forum about support for deferred constraints.
Looks to me that Hibernate checks to strictly.
Lets analyze this code:
(DefaultDeleteEventListener.java)
Code:
protected final void deleteEntity(
final EventSource session,
final Object entity,
final EntityEntry entityEntry,
final boolean isCascadeDeleteEnabled,
final EntityPersister persister)
throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace(
"deleting " +
MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
);
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
Type[] propTypes = persister.getPropertyTypes();
final Object version = entityEntry.getVersion();
final Object[] currentState;
if ( entityEntry.getLoadedState() == null ) { //ie. the entity came in from update()
currentState = persister.getPropertyValues( entity, session.getEntityMode() );
}
else {
currentState = entityEntry.getLoadedState();
}
final Object[] deletedState = new Object[propTypes.length];
TypeFactory.deepCopy(
currentState,
propTypes,
persister.getPropertyUpdateability(),
deletedState,
session
);
entityEntry.setDeletedState(deletedState);
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 free lines does the check which throws an error.
1) What is the reason for checking of nullability / transient when deleting an object?
This object is being just deleted, so who cares if is has 'intermediate' null or transient value in the field?
2) If there is a sense for such checking, what to do to support deferred contstraint in this case?