Defines the default delete event listener used by hibernate for deleting entities
from the datastore in response to generated delete events.
| Method from org.hibernate.event.def.DefaultDeleteEventListener Detail: |
protected void cascadeAfterDelete(EventSource session,
EntityPersister persister,
Object entity,
Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to many-to-one AFTER the parent was deleted
new Cascade( CascadingAction.DELETE, Cascade.BEFORE_INSERT_AFTER_DELETE, session )
.cascade( persister, entity, transientEntities );
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
session.setCacheMode( cacheMode );
}
}
|
protected void cascadeBeforeDelete(EventSource session,
EntityPersister persister,
Object entity,
EntityEntry entityEntry,
Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to collections BEFORE the collection owner is deleted
new Cascade( CascadingAction.DELETE, Cascade.AFTER_INSERT_BEFORE_DELETE, session )
.cascade( persister, entity, transientEntities );
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
session.setCacheMode( cacheMode );
}
}
|
protected final void deleteEntity(EventSource session,
Object entity,
EntityEntry entityEntry,
boolean isCascadeDeleteEnabled,
EntityPersister persister,
Set transientEntities) {
if ( log.isTraceEnabled() ) {
log.trace(
"deleting " +
MessageHelper.infoString( persister, entityEntry.getId(), session.getFactory() )
);
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
final 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 = createDeletedState( persister, currentState, 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, transientEntities );
new ForeignKeys.Nullifier( entity, true, false, session )
.nullifyTransientReferences( entityEntry.getDeletedState(), propTypes );
new Nullability( session ).checkNullability( entityEntry.getDeletedState(), persister, true );
persistenceContext.getNullifiableEntityKeys().add( key );
// Ensures that containing deletions happen before sub-deletions
session.getActionQueue().addAction(
new EntityDeleteAction(
entityEntry.getId(),
deletedState,
version,
entity,
persister,
isCascadeDeleteEnabled,
session
)
);
cascadeAfterDelete( session, persister, entity, transientEntities );
// the entry will be removed after the flush, and will no longer
// override the stale snapshot
// This is now handled by removeEntity() in EntityDeleteAction
//persistenceContext.removeDatabaseSnapshot(key);
}
Perform the entity deletion. Well, as with most operations, does not
really perform it; just schedules an action/execution with the
org.hibernate.engine.ActionQueue for execution during flush. |
protected void deleteTransientEntity(EventSource session,
Object entity,
boolean cascadeDeleteEnabled,
EntityPersister persister,
Set transientEntities) {
log.info( "handling transient entity in delete processing" );
if ( transientEntities.contains( entity ) ) {
log.trace( "already handled transient entity; skipping" );
return;
}
transientEntities.add( entity );
cascadeBeforeDelete( session, persister, entity, null, transientEntities );
cascadeAfterDelete( session, persister, entity, transientEntities );
}
We encountered a delete request on a transient instance.
This is a deviation from historical Hibernate (pre-3.2) behavior to
align with the JPA spec, which states that transient entities can be
passed to remove operation in which case cascades still need to be
performed. |
protected boolean invokeDeleteLifecycle(EventSource session,
Object entity,
EntityPersister persister) {
if ( persister.implementsLifecycle( session.getEntityMode() ) ) {
log.debug( "calling onDelete()" );
if ( ( ( Lifecycle ) entity ).onDelete( session ) ) {
log.debug( "deletion vetoed by onDelete()" );
return true;
}
}
return false;
}
|
public void onDelete(DeleteEvent event) throws HibernateException {
onDelete( event, new IdentitySet() );
}
Handle the given delete event. |
public void onDelete(DeleteEvent event,
Set transientEntities) throws HibernateException {
final EventSource source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContext();
Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
EntityEntry entityEntry = persistenceContext.getEntry( entity );
final EntityPersister persister;
final Serializable id;
final Object version;
if ( entityEntry == null ) {
log.trace( "entity was not persistent in delete processing" );
persister = source.getEntityPersister( event.getEntityName(), entity );
if ( ForeignKeys.isTransient( persister.getEntityName(), entity, null, source ) ) {
deleteTransientEntity( source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities );
// EARLY EXIT!!!
return;
}
else {
performDetachedEntityDeletionCheck( event );
}
id = persister.getIdentifier( entity, source.getEntityMode() );
if ( id == null ) {
throw new TransientObjectException(
"the detached instance passed to delete() had a null identifier"
);
}
EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
persistenceContext.checkUniqueness( key, entity );
new OnUpdateVisitor( source, id, entity ).process( entity, persister );
version = persister.getVersion( entity, source.getEntityMode() );
entityEntry = persistenceContext.addEntity(
entity,
Status.MANAGED,
persister.getPropertyValues( entity, source.getEntityMode() ),
key,
version,
LockMode.NONE,
true,
persister,
false,
false
);
}
else {
log.trace( "deleting a persistent instance" );
if ( entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE ) {
log.trace( "object was already deleted" );
return;
}
persister = entityEntry.getPersister();
id = entityEntry.getId();
version = entityEntry.getVersion();
}
/*if ( !persister.isMutable() ) {
throw new HibernateException(
"attempted to delete an object of immutable class: " +
MessageHelper.infoString(persister)
);
}*/
if ( invokeDeleteLifecycle( source, entity, persister ) ) {
return;
}
deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), persister, transientEntities );
if ( source.getFactory().getSettings().isIdentifierRollbackEnabled() ) {
persister.resetIdentifier( entity, id, version, source.getEntityMode() );
}
}
Handle the given delete event. This is the cascaded form. |
protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
// ok in normal Hibernate usage to delete a detached entity; JPA however
// forbids it, thus this is a hook for HEM to affect this behavior
}
Called when we have recognized an attempt to delete a detached entity.
This is perfectly valid in Hibernate usage; JPA, however, forbids this.
Thus, this is a hook for HEM to affect this behavior. |