move check for remove(detached) to SessionImpl for consistency/simplicity

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-09-01 23:59:25 +02:00
parent f7db3f0005
commit 302dd29be1
4 changed files with 37 additions and 63 deletions

View File

@ -30,7 +30,6 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.FlushEntityEvent;
import org.hibernate.event.spi.FlushEntityEventListener;
@ -50,14 +49,10 @@ import static org.hibernate.engine.internal.Collections.skipRemoval;
*
* @author Steve Ebersole
*/
public abstract class AbstractFlushingEventListener implements JpaBootstrapSensitive {
public abstract class AbstractFlushingEventListener {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( MethodHandles.lookup(), CoreMessageLogger.class, AbstractFlushingEventListener.class.getName() );
@Override
public void wasJpaBootstrap(boolean wasJpaBootstrap) {
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Pre-flushing section
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -28,7 +28,6 @@ import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.JpaBootstrapSensitive;
import org.hibernate.event.spi.DeleteContext;
import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.DeleteEventListener;
@ -60,22 +59,16 @@ import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
*
* @author Steve Ebersole
*/
public class DefaultDeleteEventListener implements DeleteEventListener, CallbackRegistryConsumer, JpaBootstrapSensitive {
public class DefaultDeleteEventListener implements DeleteEventListener, CallbackRegistryConsumer {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultDeleteEventListener.class );
private CallbackRegistry callbackRegistry;
private boolean jpaBootstrap;
@Override
public void injectCallbackRegistry(CallbackRegistry callbackRegistry) {
this.callbackRegistry = callbackRegistry;
}
@Override
public void wasJpaBootstrap(boolean wasJpaBootstrap) {
this.jpaBootstrap = wasJpaBootstrap;
}
/**
* Handle the given delete event.
*
@ -173,7 +166,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
deleteTransientEntity( source, entity, persister, transientEntities );
}
else {
performDetachedEntityDeletionCheck( event );
deleteDetachedEntity( event, transientEntities, entity, persister, source );
}
}
@ -315,29 +307,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
|| callbackRegistry.hasRegisteredCallbacks( mappedClass, CallbackType.POST_REMOVE );
}
/**
* Called when we have recognized an attempt to delete a detached entity.
* <p>
* This is perfectly legal in regular Hibernate usage; the JPA spec,
* however, forbids it.
*/
protected void performDetachedEntityDeletionCheck(DeleteEvent event) {
if ( jpaBootstrap ) {
disallowDeletionOfDetached( event );
}
}
private void disallowDeletionOfDetached(DeleteEvent event) {
final EventSource source = event.getSession();
final String explicitEntityName = event.getEntityName();
final EntityPersister persister = source.getEntityPersister( explicitEntityName, event.getObject() );
final Object id = persister.getIdentifier( event.getObject(), source );
final String entityName = explicitEntityName == null
? source.guessEntityName( event.getObject() )
: explicitEntityName;
throw new IllegalArgumentException( "Given entity is not associated with the persistence context [" + entityName + "#" + id + "]" );
}
/**
* We encountered a delete request on a transient instance.
* <p>

View File

@ -10,7 +10,10 @@ package org.hibernate.event.service.spi;
* Defines an event listener that is sensitive to whether a native or jpa bootstrap was performed
*
* @author Steve Ebersole
*
* @deprecated This is no longer implemented by any listener
*/
@Deprecated(since = "7")
public interface JpaBootstrapSensitive {
void wasJpaBootstrap(boolean wasJpaBootstrap);
}

View File

@ -354,10 +354,10 @@ public class SessionImpl
}
}
private Object getSessionProperty(final String name) {
private Object getSessionProperty(String propertyName) {
return properties == null
? fastSessionServices.defaultSessionProperties.get( name )
: properties.get( name );
? fastSessionServices.defaultSessionProperties.get( propertyName )
: properties.get( propertyName );
}
@Override
@ -464,9 +464,7 @@ public class SessionImpl
final ActionQueue actionQueue = getActionQueue();
if ( actionQueue.hasBeforeTransactionActions() || actionQueue.hasAfterTransactionActions() ) {
log.warn(
"On close, shared Session had before/after transaction actions that have not yet been processed"
);
log.warn( "On close, shared Session had before/after transaction actions that have not yet been processed" );
}
return false;
}
@ -575,11 +573,8 @@ public class SessionImpl
}
if ( e.getStatus().isDeletedOrGone() ) {
throw new ObjectDeletedException(
"The given object was deleted",
e.getId(),
e.getPersister().getEntityName()
);
throw new ObjectDeletedException( "The given object was deleted", e.getId(),
e.getPersister().getEntityName() );
}
return e.getLockMode();
@ -895,6 +890,7 @@ public class SessionImpl
}
private void fireDelete(final DeleteEvent event) {
checkEntityManagedIfJpa( event.getEntityName(), event.getObject() );
try {
pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_DELETE
@ -916,6 +912,7 @@ public class SessionImpl
}
private void fireDelete(final DeleteEvent event, final DeleteContext transientEntities) {
checkEntityManagedIfJpa( event.getEntityName(), event.getObject() );
try {
pulseTransactionCoordinator();
fastSessionServices.eventListenerGroup_DELETE
@ -1204,8 +1201,17 @@ public class SessionImpl
private void checkEntityManaged(String entityName, Object entity) {
if ( !getSessionFactory().getSessionFactoryOptions().isAllowRefreshDetachedEntity() ) {
if ( !managed( entityName, entity ) ) {
throw new IllegalArgumentException(
"Given entity is not associated with the persistence context" );
throw new IllegalArgumentException( "Given entity is not associated with the persistence context" );
}
}
}
private void checkEntityManagedIfJpa(String entityName, Object entity) {
if ( getSessionFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
if ( !managed( entityName, entity )
// just in case it was already deleted
&& !persistenceContext.isEntryFor( entity ) ) {
throw new IllegalArgumentException( "Given entity is not associated with the persistence context" );
}
}
}
@ -1423,8 +1429,9 @@ public class SessionImpl
}
/**
* Get the id value for an object that is actually associated with the session. This
* is a bit stricter than getEntityIdentifierIfNotUnsaved().
* Get the id value for an object that is actually associated with the session.
* This is a bit stricter than
* {@link org.hibernate.engine.internal.ForeignKeys#getEntityIdentifierIfNotUnsaved}.
*/
@Override
public Object getContextEntityIdentifier(Object object) {
@ -1457,20 +1464,20 @@ public class SessionImpl
try {
final LazyInitializer lazyInitializer = extractLazyInitializer( object );
if ( lazyInitializer != null ) {
//do not use proxiesByKey, since not all
//proxies that point to this session's
//instances are in that collection!
// don't use proxiesByKey, since not all
// proxies that point to this session's
// instances are in that collection!
if ( lazyInitializer.isUninitialized() ) {
//if it is an uninitialized proxy, pointing
//with this session, then when it is accessed,
//the underlying instance will be "contained"
// if it's an uninitialized proxy associated
// with this session, then when it is accessed,
// the underlying instance will be "contained"
return lazyInitializer.getSession() == this;
}
else {
//if it is initialized, see if the underlying
//instance is contained, since we need to
//account for the fact that it might have been
//evicted
// if it's initialized, see if the underlying
// instance is contained, since we need to
// account for the fact that it might have been
// evicted
object = lazyInitializer.getImplementation();
}
}