misc cleanups to default events listeners

This commit is contained in:
Gavin 2023-04-10 01:42:53 +02:00 committed by Gavin King
parent bd57af6d97
commit 49fb2dce8a
13 changed files with 178 additions and 176 deletions

View File

@ -71,7 +71,7 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
LOG.trace( "Flushing session" );
EventSource session = event.getSession();
final EventSource session = event.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
session.getInterceptor().preFlush( persistenceContext.managedEntitiesIterator() );
@ -139,14 +139,20 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
//safe from concurrent modification because of how concurrentEntries() is implemented on IdentityMap
for ( Map.Entry<Object,EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) {
// for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) {
EntityEntry entry = me.getValue();
Status status = entry.getStatus();
if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) {
final EntityEntry entry = me.getValue();
if ( flushable( entry ) ) {
cascadeOnFlush( session, entry.getPersister(), me.getKey(), context );
}
}
}
private static boolean flushable(EntityEntry entry) {
final Status status = entry.getStatus();
return status == Status.MANAGED
|| status == Status.SAVING
|| status == Status.READ_ONLY;
}
private void cascadeOnFlush(EventSource session, EntityPersister persister, Object object, PersistContext anything)
throws HibernateException {
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
@ -209,9 +215,8 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
for ( Map.Entry<Object,EntityEntry> me : entityEntries ) {
// Update the status of the object and if necessary, schedule an update
EntityEntry entry = me.getValue();
Status status = entry.getStatus();
final EntityEntry entry = me.getValue();
final Status status = entry.getStatus();
if ( status != Status.LOADING && status != Status.GONE ) {
entityEvent = createOrReuseEventInstance( entityEvent, source, me.getKey(), entry );
@ -238,15 +243,15 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
EventSource source,
Object key,
EntityEntry entry) {
FlushEntityEvent entityEvent = possiblyValidExistingInstance;
if ( entityEvent == null || (! entityEvent.isAllowedToReuse() ) ) {
final FlushEntityEvent entityEvent = possiblyValidExistingInstance;
if ( entityEvent == null || !entityEvent.isAllowedToReuse() ) {
//need to create a new instance
entityEvent = new FlushEntityEvent( source, key, entry );
return new FlushEntityEvent( source, key, entry );
}
else {
entityEvent.resetAndReuseEventInstance( key, entry );
return entityEvent;
}
return entityEvent;
}
/**
@ -351,8 +356,8 @@ public abstract class AbstractFlushingEventListener implements JpaBootstrapSensi
try {
jdbcCoordinator.flushBeginning();
persistenceContext.setFlushing( true );
// we need to lock the collection caches before executing entity inserts/updates in order to
// account for bi-directional associations
// we need to lock the collection caches before executing entity inserts/updates
// in order to account for bidirectional associations
final ActionQueue actionQueue = session.getActionQueue();
actionQueue.prepareActions();
actionQueue.executeActions();

View File

@ -42,6 +42,7 @@ import static org.hibernate.engine.internal.Versioning.getVersion;
import static org.hibernate.engine.internal.Versioning.seedVersion;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.id.IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR;
import static org.hibernate.pretty.MessageHelper.infoString;
/**
* A convenience base class for listeners responding to save events.
@ -115,7 +116,7 @@ public abstract class AbstractSaveEventListener<C>
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
final EntityPersister persister = source.getEntityPersister( entityName, entity );
Generator generator = persister.getGenerator();
final Generator generator = persister.getGenerator();
if ( !generator.generatedOnExecution() ) {
final Object generatedId = ( (BeforeExecutionGenerator) generator ).generate( source, entity, null, INSERT );
if ( generatedId == null ) {
@ -169,7 +170,7 @@ public abstract class AbstractSaveEventListener<C>
boolean requiresImmediateIdAccess) {
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Saving {0}", MessageHelper.infoString( persister, id, source.getFactory() ) );
LOG.tracev( "Saving {0}", infoString( persister, id, source.getFactory() ) );
}
final EntityKey key = entityKey( entity, id, persister, useIdentityColumn, source );
@ -250,13 +251,13 @@ public abstract class AbstractSaveEventListener<C>
final Object id = key == null ? null : key.getIdentifier();
boolean shouldDelayIdentityInserts = !source.isTransactionInProgress() && !requiresImmediateIdAccess;
final boolean shouldDelayIdentityInserts = !source.isTransactionInProgress() && !requiresImmediateIdAccess;
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
// Put a placeholder in entries, so we don't recurse back and try to save() the
// same object again. QUESTION: should this be done before onSave() is called?
// likewise, should it be done before onUpdate()?
EntityEntry original = persistenceContext.addEntry(
final EntityEntry original = persistenceContext.addEntry(
entity,
Status.SAVING,
null,
@ -287,9 +288,9 @@ public abstract class AbstractSaveEventListener<C>
final Object finalId = handleGeneratedId( useIdentityColumn, id, insert );
EntityEntry newEntry = persistenceContext.getEntry( entity );
final EntityEntry newEntry = persistenceContext.getEntry( entity );
if ( newEntry != original ) {
EntityEntryExtraState extraState = newEntry.getExtraState( EntityEntryExtraState.class );
final EntityEntryExtraState extraState = newEntry.getExtraState( EntityEntryExtraState.class );
if ( extraState == null ) {
newEntry.addExtraState( original.getExtraState( EntityEntryExtraState.class ) );
}
@ -301,7 +302,7 @@ public abstract class AbstractSaveEventListener<C>
private static Object handleGeneratedId(boolean useIdentityColumn, Object id, AbstractEntityInsertAction insert) {
if ( useIdentityColumn && insert.isEarlyInsert() ) {
if ( insert instanceof EntityIdentityInsertAction ) {
Object generatedId = ((EntityIdentityInsertAction) insert).getGeneratedId();
final Object generatedId = ((EntityIdentityInsertAction) insert).getGeneratedId();
insert.handleNaturalIdPostSaveNotifications( generatedId );
return generatedId;
}
@ -318,8 +319,8 @@ public abstract class AbstractSaveEventListener<C>
}
private Object[] cloneAndSubstituteValues(Object entity, EntityPersister persister, C context, EventSource source, Object id) {
Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap(context), source );
Type[] types = persister.getPropertyTypes();
final Object[] values = persister.getPropertyValuesToInsert( entity, getMergeMap( context ), source );
final Type[] types = persister.getPropertyTypes();
boolean substitute = substituteValuesIfNecessary( entity, id, values, persister, source );
if ( persister.hasCollections() ) {
@ -349,7 +350,7 @@ public abstract class AbstractSaveEventListener<C>
EventSource source,
boolean shouldDelayIdentityInserts) {
if ( useIdentityColumn ) {
EntityIdentityInsertAction insert = new EntityIdentityInsertAction(
final EntityIdentityInsertAction insert = new EntityIdentityInsertAction(
values,
entity,
persister,
@ -396,7 +397,7 @@ public abstract class AbstractSaveEventListener<C>
Object[] values,
Type[] types,
EventSource source) {
WrapVisitor visitor = new WrapVisitor( entity, id, source );
final WrapVisitor visitor = new WrapVisitor( entity, id, source );
// substitutes into values by side effect
visitor.processEntityPropertyValues( values, types );
return visitor.isSubstitutionRequired();

View File

@ -131,17 +131,17 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
}
private static void deleteOwnedCollections(Type type, Object key, EventSource session) {
MappingMetamodelImplementor mappingMetamodel = session.getFactory().getMappingMetamodel();
ActionQueue actionQueue = session.getActionQueue();
final MappingMetamodelImplementor mappingMetamodel = session.getFactory().getMappingMetamodel();
final ActionQueue actionQueue = session.getActionQueue();
if ( type.isCollectionType() ) {
String role = ( (CollectionType) type ).getRole();
CollectionPersister persister = mappingMetamodel.getCollectionDescriptor(role);
final String role = ( (CollectionType) type ).getRole();
final CollectionPersister persister = mappingMetamodel.getCollectionDescriptor(role);
if ( !persister.isInverse() ) {
actionQueue.addAction( new CollectionRemoveAction( persister, key, session ) );
}
}
else if ( type.isComponentType() ) {
Type[] subtypes = ( (CompositeType) type ).getSubtypes();
final Type[] subtypes = ( (CompositeType) type ).getSubtypes();
for ( Type subtype : subtypes ) {
deleteOwnedCollections( subtype, key, session );
}
@ -151,7 +151,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
private void delete(DeleteEvent event, DeleteContext transientEntities) {
final PersistenceContext persistenceContext = event.getSession().getPersistenceContextInternal();
final Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
EntityEntry entityEntry = persistenceContext.getEntry( entity );
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
if ( entityEntry == null ) {
deleteTransientInstance( event, transientEntities, entity );
}
@ -165,7 +165,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
final EventSource source = event.getSession();
EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
if ( ForeignKeys.isTransient( persister.getEntityName(), entity, null, source ) ) {
deleteTransientEntity( source, entity, persister, transientEntities );
}
@ -186,7 +186,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
final Object version = persister.getVersion( entity );
EntityEntry entityEntry = persistenceContext.addEntity(
final EntityEntry entityEntry = persistenceContext.addEntity(
entity,
persister.isMutable() ? Status.MANAGED : Status.READ_ONLY,
persister.getValues( entity ),
@ -214,18 +214,19 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
|| source.getPersistenceContextInternal()
.containsDeletedUnloadedEntityKey( entityEntry.getEntityKey() ) ) {
LOG.trace( "Object was already deleted" );
return;
}
delete(
event,
transientEntities,
source,
entity,
entityEntry.getPersister(),
entityEntry.getId(),
entityEntry.getVersion(),
entityEntry
);
else {
delete(
event,
transientEntities,
source,
entity,
entityEntry.getPersister(),
entityEntry.getId(),
entityEntry.getVersion(),
entityEntry
);
}
}
private void delete(
@ -330,12 +331,13 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
EntityPersister persister,
DeleteContext transientEntities) {
LOG.handlingTransientEntity();
if ( !transientEntities.add( entity ) ) {
LOG.trace( "Already handled transient entity; skipping" );
return;
if ( transientEntities.add( entity ) ) {
cascadeBeforeDelete( session, persister, entity, transientEntities );
cascadeAfterDelete( session, persister, entity, transientEntities );
}
else {
LOG.trace( "Already handled transient entity; skipping" );
}
cascadeBeforeDelete( session, persister, entity, transientEntities );
cascadeAfterDelete( session, persister, entity, transientEntities );
}
/**

View File

@ -128,10 +128,11 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
public void onFlushEntity(FlushEntityEvent event) throws HibernateException {
final Object entity = event.getEntity();
final EntityEntry entry = event.getEntityEntry();
final EventSource session = event.getSession();
final boolean mightBeDirty = entry.requiresDirtyCheck( entity );
final Object[] values = getValues( entity, entry, mightBeDirty, event.getSession() );
final Object[] values = getValues( entity, entry, mightBeDirty, session );
event.setPropertyValues( values );
@ -153,7 +154,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
// Search for collections by reachability, updating their role.
// We don't want to touch collections reachable from a deleted object
if ( persister.hasCollections() ) {
new FlushVisitor(event.getSession(), entity )
new FlushVisitor( session, entity )
.processEntityPropertyValues( values, persister.getPropertyTypes() );
}
}
@ -194,7 +195,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
// because collections need wrapping but changes to _them_
// don't dirty the container. Also, for versioned data, we
// need to wrap before calling searchForDirtyCollections
WrapVisitor visitor = new WrapVisitor( event.getEntity(), entry.getId() , event.getSession() );
final WrapVisitor visitor = new WrapVisitor( event.getEntity(), entry.getId(), event.getSession() );
// substitutes into values by side effect
visitor.processEntityPropertyValues( values, persister.getPropertyTypes() );
return visitor.isSubstitutionRequired();
@ -205,7 +206,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
}
private boolean isUpdateNecessary(final FlushEntityEvent event, final boolean mightBeDirty) {
EntityEntry entry = event.getEntityEntry();
final EntityEntry entry = event.getEntityEntry();
if ( mightBeDirty || entry.getStatus() == Status.DELETED ) {
// compare to cached state (ignoring collections unless versioned)
dirtyCheck( event );
@ -213,11 +214,12 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
return true;
}
else {
processIfSelfDirtinessTracker( event.getEntity(), SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
EventSource source = event.getSession();
final Object entity = event.getEntity();
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
final EventSource source = event.getSession();
source.getFactory()
.getCustomEntityDirtinessStrategy()
.resetDirty( event.getEntity(), entry.getPersister(), source );
.resetDirty( entity, entry.getPersister(), source );
return false;
}
}
@ -255,9 +257,9 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
values,
dirtyProperties,
event.hasDirtyCollection(),
status == Status.DELETED && !entry.isModifiableEntity() ?
persister.getValues( entity ) :
entry.getLoadedState(),
status == Status.DELETED && !entry.isModifiableEntity()
? persister.getValues( entity )
: entry.getLoadedState(),
entry.getVersion(),
nextVersion,
entity,
@ -384,10 +386,10 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
* Convenience method to retrieve an entities next version value
*/
private Object getNextVersion(FlushEntityEvent event) throws HibernateException {
EntityEntry entry = event.getEntityEntry();
EntityPersister persister = entry.getPersister();
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
if ( persister.isVersioned() ) {
Object[] values = event.getPropertyValues();
final Object[] values = event.getPropertyValues();
if ( entry.isBeingReplicated() ) {
return getVersion( values, persister );
}
@ -402,7 +404,6 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
else {
return null;
}
}
private static boolean isVersionIncrementRequired(FlushEntityEvent event, EntityEntry entry) {
@ -432,9 +433,10 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
}
private boolean hasDirtyCollections(FlushEntityEvent event) {
EntityPersister persister = event.getEntityEntry().getPersister();
if ( isCollectionDirtyCheckNecessary( persister, event.getEntityEntry().getStatus() ) ) {
DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor(
final EntityEntry entityEntry = event.getEntityEntry();
final EntityPersister persister = entityEntry.getPersister();
if ( isCollectionDirtyCheckNecessary( persister, entityEntry.getStatus() ) ) {
final DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor(
event.getEntity(),
event.getSession(),
persister.getPropertyVersionability()
@ -576,8 +578,8 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
}
}
}
EventSource session = event.getSession();
DirtyCheckContextImpl context = new DirtyCheckContextImpl();
final EventSource session = event.getSession();
final DirtyCheckContextImpl context = new DirtyCheckContextImpl();
session.getFactory().getCustomEntityDirtinessStrategy()
.findDirty( event.getEntity(), event.getEntityEntry().getPersister(), session, context );
return context.found;
@ -675,13 +677,10 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
}
}
private static Object[] getDatabaseSnapshot(
EntityPersister persister,
Object id,
SessionImplementor session) {
private static Object[] getDatabaseSnapshot(EntityPersister persister, Object id, SessionImplementor session) {
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
if ( persister.isSelectBeforeUpdateRequired() ) {
Object[] snapshot = persistenceContext.getDatabaseSnapshot( id, persister );
final Object[] snapshot = persistenceContext.getDatabaseSnapshot( id, persister );
if ( snapshot == null ) {
//do we even really need this? the update will fail anyway....
final StatisticsImplementor statistics = session.getFactory().getStatistics();

View File

@ -24,6 +24,8 @@ import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.results.internal.ResultsHelper;
import org.hibernate.stat.spi.StatisticsImplementor;
import static org.hibernate.pretty.MessageHelper.collectionInfoString;
/**
* @author Gavin King
*/
@ -34,35 +36,25 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
* called by a collection that wants to initialize itself
*/
public void onInitializeCollection(InitializeCollectionEvent event) throws HibernateException {
PersistentCollection<?> collection = event.getCollection();
SessionImplementor source = event.getSession();
final PersistentCollection<?> collection = event.getCollection();
final SessionImplementor source = event.getSession();
CollectionEntry ce = source.getPersistenceContextInternal().getCollectionEntry( collection );
final CollectionEntry ce = source.getPersistenceContextInternal().getCollectionEntry( collection );
if ( ce == null ) {
throw new HibernateException( "collection was evicted" );
}
if ( !collection.wasInitialized() ) {
final CollectionPersister ceLoadedPersister = ce.getLoadedPersister();
final CollectionPersister loadedPersister = ce.getLoadedPersister();
final Object loadedKey = ce.getLoadedKey();
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Initializing collection {0}",
MessageHelper.collectionInfoString(
ceLoadedPersister,
collection,
ce.getLoadedKey(),
source
)
collectionInfoString( loadedPersister, collection, loadedKey, source )
);
LOG.trace( "Checking second-level cache" );
}
final boolean foundInCache = initializeCollectionFromCache(
ce.getLoadedKey(),
ceLoadedPersister,
collection,
source
);
final boolean foundInCache = initializeCollectionFromCache( loadedKey, loadedPersister, collection, source );
if ( foundInCache ) {
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Collection initialized from cache" );
@ -72,17 +64,15 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Collection not cached" );
}
ceLoadedPersister.initialize( ce.getLoadedKey(), source );
handlePotentiallyEmptyCollection( collection, source, ce, ceLoadedPersister );
loadedPersister.initialize( loadedKey, source );
handlePotentiallyEmptyCollection( collection, source, ce, loadedPersister );
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Collection initialized" );
}
final StatisticsImplementor statistics = source.getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.fetchCollection(
ceLoadedPersister.getRole()
);
statistics.fetchCollection( loadedPersister.getRole() );
}
}
}
@ -92,12 +82,12 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
PersistentCollection<?> collection,
SessionImplementor source,
CollectionEntry ce,
CollectionPersister ceLoadedPersister) {
CollectionPersister loadedPersister) {
if ( !collection.wasInitialized() ) {
collection.initializeEmptyCollection( ceLoadedPersister );
collection.initializeEmptyCollection( loadedPersister );
ResultsHelper.finalizeCollectionLoading(
source.getPersistenceContext(),
ceLoadedPersister,
loadedPersister,
collection,
ce.getLoadedKey(),
true
@ -142,16 +132,10 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
final StatisticsImplementor statistics = factory.getStatistics();
if ( statistics.isStatisticsEnabled() ) {
if ( ce == null ) {
statistics.collectionCacheMiss(
persister.getNavigableRole(),
cacheAccessStrategy.getRegion().getName()
);
statistics.collectionCacheMiss( persister.getNavigableRole(), cacheAccessStrategy.getRegion().getName() );
}
else {
statistics.collectionCacheHit(
persister.getNavigableRole(),
cacheAccessStrategy.getRegion().getName()
);
statistics.collectionCacheHit( persister.getNavigableRole(), cacheAccessStrategy.getRegion().getName() );
}
}
@ -159,7 +143,7 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
return false;
}
CollectionCacheEntry cacheEntry = (CollectionCacheEntry)
final CollectionCacheEntry cacheEntry = (CollectionCacheEntry)
persister.getCacheEntryStructure().destructure( ce, factory );
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();

View File

@ -42,6 +42,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.pretty.MessageHelper.infoString;
/**
* Defines the default load event listeners used by hibernate for loading entities
@ -63,11 +64,16 @@ public class DefaultLoadEventListener implements LoadEventListener {
if ( persister == null ) {
throw new HibernateException( "Unable to locate persister: " + event.getEntityClassName() );
}
checkId( event, loadType, persister );
doOnLoad( persister, event, loadType );
}
private void checkId(LoadEvent event, LoadType loadType, EntityPersister persister) {
final Object id = event.getEntityId();
if ( !persister.getIdentifierMapping().getJavaType().isInstance( id )
&& !( id instanceof DelayedPostInsertIdentifier ) ) {
final Class<?> idClass = persister.getIdentifierType().getReturnedClass();
if ( handleIdType( persister, event, loadType, idClass) ) {
if ( handleIdType( persister, event, loadType, idClass ) ) {
throw new TypeMismatchException(
"Supplied id had wrong type: entity '" + persister.getEntityName()
+ "' has id type '" + idClass
@ -75,7 +81,6 @@ public class DefaultLoadEventListener implements LoadEventListener {
);
}
}
doOnLoad( persister, event, loadType );
}
protected EntityPersister getPersister(final LoadEvent event) {
@ -193,7 +198,7 @@ public class DefaultLoadEventListener implements LoadEventListener {
if ( session.getPersistenceContextInternal().getEntry( event.getInstanceToLoad() ) != null ) {
throw new PersistentObjectException(
"attempted to load into an instance that was already associated with the session: "
+ MessageHelper.infoString( persister, event.getEntityId(), session.getFactory() )
+ infoString( persister, event.getEntityId(), session.getFactory() )
);
}
persister.setIdentifier( event.getInstanceToLoad(), event.getEntityId(), session);
@ -227,7 +232,7 @@ public class DefaultLoadEventListener implements LoadEventListener {
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Loading entity: {0}",
MessageHelper.infoString( persister, event.getEntityId(), persister.getFactory() )
infoString( persister, event.getEntityId(), persister.getFactory() )
);
}
if ( hasBytecodeProxy( persister, options ) ) {
@ -519,19 +524,20 @@ public class DefaultLoadEventListener implements LoadEventListener {
* @return The loaded entity, or null.
*/
private Object doLoad(LoadEvent event, EntityPersister persister, EntityKey keyToLoad, LoadType options) {
final EventSource session = event.getSession();
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Attempting to resolve: {0}",
MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
infoString( persister, event.getEntityId(), session.getFactory() )
);
}
if ( event.getSession().getPersistenceContextInternal()
.containsDeletedUnloadedEntityKey( keyToLoad ) ) {
if ( session.getPersistenceContextInternal().containsDeletedUnloadedEntityKey( keyToLoad ) ) {
return null;
}
else {
PersistenceContextEntry persistenceContextEntry
final PersistenceContextEntry persistenceContextEntry
= CacheEntityLoaderHelper.INSTANCE.loadFromSessionCache( event, keyToLoad, options );
final Object entity = persistenceContextEntry.getEntity();
if ( entity != null ) {
@ -573,7 +579,7 @@ public class DefaultLoadEventListener implements LoadEventListener {
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Resolved object in second-level cache: {0}",
MessageHelper.infoString( persister, event.getEntityId(), session.getFactory() )
infoString( persister, event.getEntityId(), session.getFactory() )
);
}
return entity;
@ -582,7 +588,7 @@ public class DefaultLoadEventListener implements LoadEventListener {
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Object not resolved in any cache: {0}",
MessageHelper.infoString( persister, event.getEntityId(), session.getFactory() )
infoString( persister, event.getEntityId(), session.getFactory() )
);
}
return loadFromDatasource( event, persister );

View File

@ -56,9 +56,9 @@ public class DefaultLockEventListener extends AbstractLockUpgradeEventListener i
LOG.explicitSkipLockedLockCombo();
}
SessionImplementor source = event.getSession();
final SessionImplementor source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
final Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
//TODO: if object was an uninitialized proxy, this is inefficient,
// resulting in two SQL selects
@ -78,7 +78,7 @@ public class DefaultLockEventListener extends AbstractLockUpgradeEventListener i
}
private void cascadeOnLock(LockEvent event, EntityPersister persister, Object entity) {
EventSource source = event.getSession();
final EventSource source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
persistenceContext.incrementCascadeLevel();
try {

View File

@ -25,7 +25,6 @@ import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.spi.EntityCopyObserver;
import org.hibernate.event.spi.EventSource;
@ -50,6 +49,7 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTra
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
import static org.hibernate.event.internal.EntityState.getEntityState;
/**
* Defines the default copy event listener used by hibernate for copying entities
@ -147,13 +147,13 @@ public class DefaultMergeEventListener
private void merge(MergeEvent event, MergeContext copiedAlready, Object entity) {
switch ( entityState( event, entity ) ) {
case DETACHED:
entityIsDetached(event, copiedAlready);
entityIsDetached( event, copiedAlready );
break;
case TRANSIENT:
entityIsTransient(event, copiedAlready);
entityIsTransient( event, copiedAlready );
break;
case PERSISTENT:
entityIsPersistent(event, copiedAlready);
entityIsPersistent( event, copiedAlready );
break;
default: //DELETED
throw new ObjectDeletedException(
@ -186,7 +186,7 @@ public class DefaultMergeEventListener
}
}
}
return EntityState.getEntityState( entity, event.getEntityName(), entry, source, false );
return getEntityState( entity, event.getEntityName(), entry, source, false );
}
protected void entityIsPersistent(MergeEvent event, MergeContext copyCache) {
@ -343,7 +343,6 @@ public class DefaultMergeEventListener
markInterceptorDirty( entity, target );
event.setResult( result );
}
}
private static Object targetEntity(MergeEvent event, Object entity, EntityPersister persister, Object id, Object result) {
@ -380,7 +379,7 @@ public class DefaultMergeEventListener
}
else {
// check that entity id = requestedId
Object entityId = persister.getIdentifier( entity, source );
final Object entityId = persister.getIdentifier( entity, source );
if ( !persister.getIdentifierType().isEqual( id, entityId, source.getFactory() ) ) {
throw new HibernateException( "merge requested with id not matching id of passed entity" );
}
@ -400,8 +399,10 @@ public class DefaultMergeEventListener
if ( isPersistentAttributeInterceptable( incoming )
&& persister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
final PersistentAttributeInterceptor incomingInterceptor = asPersistentAttributeInterceptable( incoming ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor managedInterceptor = asPersistentAttributeInterceptable( managed ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor incomingInterceptor =
asPersistentAttributeInterceptable( incoming ).$$_hibernate_getInterceptor();
final PersistentAttributeInterceptor managedInterceptor =
asPersistentAttributeInterceptable( managed ).$$_hibernate_getInterceptor();
// todo - do we need to specially handle the case where both `incoming` and `managed` are initialized, but
// with different attributes initialized?

View File

@ -15,6 +15,7 @@ import org.hibernate.event.spi.PersistContext;
* @author Emmanuel Bernard
*/
public class DefaultPersistOnFlushEventListener extends DefaultPersistEventListener {
@Override
protected CascadingAction<PersistContext> getCascadeAction() {
return CascadingActions.PERSIST_ON_FLUSH;
}

View File

@ -21,7 +21,8 @@ import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
/**
* We do 2 things here:<ul>
* We do two things here:
* <ul>
* <li>Call {@link Lifecycle} interface if necessary</li>
* <li>Perform needed {@link EntityEntry#getLockMode()} related processing</li>
* </ul>
@ -49,34 +50,26 @@ public class DefaultPostLoadEventListener implements PostLoadEventListener, Call
throw new AssertionFailure( "possible non-threadsafe access to the session" );
}
final LockMode lockMode = entry.getLockMode();
switch (lockMode) {
switch ( entry.getLockMode() ) {
case PESSIMISTIC_FORCE_INCREMENT:
final EntityPersister persister = entry.getPersister();
final Object nextVersion = persister.forceVersionIncrement(
entry.getId(),
entry.getVersion(),
session
);
entry.forceLocked(entity, nextVersion);
final Object nextVersion = entry.getPersister()
.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
entry.forceLocked( entity, nextVersion );
break;
case OPTIMISTIC_FORCE_INCREMENT:
final EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess(entity);
session.getActionQueue().registerProcess(incrementVersion);
session.getActionQueue().registerProcess( new EntityIncrementVersionProcess( entity ) );
break;
case OPTIMISTIC:
final EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess(entity);
session.getActionQueue().registerProcess(verifyVersion);
session.getActionQueue().registerProcess( new EntityVerifyVersionProcess( entity ) );
break;
}
invokeLoadLifecycle(event, session);
invokeLoadLifecycle( event, session );
}
protected void invokeLoadLifecycle(PostLoadEvent event, EventSource session) {
if ( event.getPersister().implementsLifecycle() ) {
//log.debug( "calling onLoad()" );
( (Lifecycle) event.getEntity() ).onLoad( session, event.getId() );
}
}

View File

@ -37,6 +37,8 @@ import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import static org.hibernate.pretty.MessageHelper.infoString;
/**
* Defines the default refresh event listener used by hibernate for refreshing entities
* in response to generated refresh events.
@ -89,19 +91,18 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
final Object id;
if ( entry == null ) {
//refresh() does not pass an entityName
persister = source.getEntityPersister( event.getEntityName(), object);
id = persister.getIdentifier(object, event.getSession() );
persister = source.getEntityPersister( event.getEntityName(), object );
id = persister.getIdentifier( object, event.getSession() );
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Refreshing transient {0}",
MessageHelper.infoString( persister, id, source.getFactory() )
infoString( persister, id, source.getFactory() )
);
}
final EntityKey key = source.generateEntityKey( id, persister );
if ( persistenceContext.getEntry( key ) != null ) {
if ( persistenceContext.getEntry( source.generateEntityKey( id, persister ) ) != null ) {
throw new PersistentObjectException(
"attempted to refresh transient instance when persistent instance was already associated with the Session: " +
MessageHelper.infoString( persister, id, source.getFactory() )
"attempted to refresh transient instance when persistent instance was already associated with the Session: "
+ infoString( persister, id, source.getFactory() )
);
}
}
@ -109,7 +110,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Refreshing ",
MessageHelper.infoString( entry.getPersister(), entry.getId(), source.getFactory() )
infoString( entry.getPersister(), entry.getId(), source.getFactory() )
);
}
if ( !entry.isExistsInDatabase() ) {
@ -140,12 +141,12 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
}
}
evictEntity( object, persister, id, source);
evictCachedCollections( persister, id, source);
evictEntity( object, persister, id, source );
evictCachedCollections( persister, id, source );
final Object result = source.getLoadQueryInfluencers().fromInternalFetchProfile(
CascadingFetchProfile.REFRESH,
() -> doRefresh(event, source, object, entry, persister, id, persistenceContext)
() -> doRefresh( event, source, object, entry, persister, id, persistenceContext )
);
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
}
@ -183,7 +184,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
// Handle the requested lock-mode (if one) in relation to the entry's (if one) current lock-mode
LockOptions lockOptionsToUse = event.getLockOptions();
final LockMode requestedLockMode = lockOptionsToUse.getLockMode();
LockMode postRefreshLockMode = null;
final LockMode postRefreshLockMode;
if ( entry != null ) {
final LockMode currentLockMode = entry.getLockMode();
if ( currentLockMode.greaterThan( requestedLockMode ) ) {
@ -207,8 +208,15 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
}
else {
lockOptionsToUse.setLockMode( currentLockMode );
postRefreshLockMode = null;
}
}
else {
postRefreshLockMode = null;
}
}
else {
postRefreshLockMode = null;
}
final Object result = persister.load( id, object, lockOptionsToUse, source );
@ -245,7 +253,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
for ( Type type : types ) {
if ( type.isCollectionType() ) {
final String role = ((CollectionType) type).getRole();
CollectionPersister collectionPersister = metamodel.getCollectionDescriptor( role );
final CollectionPersister collectionPersister = metamodel.getCollectionDescriptor( role );
if ( collectionPersister.hasCache() ) {
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
@ -260,7 +268,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
}
}
else if ( type.isComponentType() ) {
CompositeType compositeType = (CompositeType) type;
final CompositeType compositeType = (CompositeType) type;
evictCachedCollections( compositeType.getSubtypes(), id, source );
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.event.internal;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.NaturalIdResolutions;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.ResolveNaturalIdEvent;
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
@ -18,6 +19,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.hibernate.pretty.MessageHelper.infoString;
/**
* Defines the default load event listeners used by hibernate for loading entities
@ -53,17 +55,17 @@ public class DefaultResolveNaturalIdEventListener
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Attempting to resolve: {0}#{1}",
MessageHelper.infoString( persister ),
infoString( persister ),
event.getNaturalIdValues()
);
}
Object entityId = resolveFromCache( event );
final Object entityId = resolveFromCache( event );
if ( entityId != null ) {
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Resolved object in cache: {0}#{1}",
MessageHelper.infoString( persister ),
infoString( persister ),
event.getNaturalIdValues()
);
}
@ -73,7 +75,7 @@ public class DefaultResolveNaturalIdEventListener
if ( LOG.isTraceEnabled() ) {
LOG.tracev(
"Object not resolved in any cache: {0}#{1}",
MessageHelper.infoString( persister ),
infoString( persister ),
event.getNaturalIdValues()
);
}
@ -88,9 +90,8 @@ public class DefaultResolveNaturalIdEventListener
*
* @return The entity from the cache, or null.
*/
protected Object resolveFromCache(final ResolveNaturalIdEvent event) {
return event.getSession().getPersistenceContextInternal()
.getNaturalIdResolutions()
protected Object resolveFromCache(ResolveNaturalIdEvent event) {
return getNaturalIdResolutions( event)
.findCachedIdByNaturalId( event.getOrderedNaturalIdValues(), event.getEntityPersister() );
}
@ -102,16 +103,14 @@ public class DefaultResolveNaturalIdEventListener
*
* @return The object loaded from the datasource, or null if not found.
*/
protected Object loadFromDatasource(final ResolveNaturalIdEvent event) {
protected Object loadFromDatasource(ResolveNaturalIdEvent event) {
final EventSource session = event.getSession();
final EntityPersister entityPersister = event.getEntityPersister();
final StatisticsImplementor statistics = session.getFactory().getStatistics();
final boolean statisticsEnabled = statistics.isStatisticsEnabled();
long startTime = 0;
if ( statisticsEnabled ) {
startTime = System.nanoTime();
}
final long startTime = statisticsEnabled ? System.nanoTime() : 0;
final Object pk = event.getEntityPersister().loadEntityIdByNaturalId(
final Object pk = entityPersister.loadEntityIdByNaturalId(
event.getOrderedNaturalIdValues(),
event.getLockOptions(),
session
@ -120,15 +119,18 @@ public class DefaultResolveNaturalIdEventListener
if ( statisticsEnabled ) {
final long endTime = System.nanoTime();
final long milliseconds = MILLISECONDS.convert( endTime - startTime, NANOSECONDS );
statistics.naturalIdQueryExecuted( event.getEntityPersister().getRootEntityName(), milliseconds );
statistics.naturalIdQueryExecuted( entityPersister.getRootEntityName(), milliseconds );
}
//PK can be null if the entity doesn't exist
if ( pk != null ) {
session.getPersistenceContextInternal()
.getNaturalIdResolutions()
.cacheResolutionFromLoad( pk, event.getOrderedNaturalIdValues(), event.getEntityPersister() );
getNaturalIdResolutions( event )
.cacheResolutionFromLoad( pk, event.getOrderedNaturalIdValues(), entityPersister );
}
return pk;
}
private static NaturalIdResolutions getNaturalIdResolutions(ResolveNaturalIdEvent event) {
return event.getSession().getPersistenceContextInternal().getNaturalIdResolutions();
}
}

View File

@ -24,7 +24,7 @@ import org.hibernate.persister.entity.EntityPersister;
public class LoaderHelper {
public static void upgradeLock(Object object, EntityEntry entry, LockOptions lockOptions, EventSource session) {
LockMode requestedLockMode = lockOptions.getLockMode();
final LockMode requestedLockMode = lockOptions.getLockMode();
if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) {
// The user requested a "greater" (i.e. more restrictive) form of
// pessimistic lock