HHH-8654 - Ability to get notified of interesting Session events

This commit is contained in:
Steve Ebersole 2013-11-15 13:04:18 -06:00
parent 1e74abf511
commit 449c558365
10 changed files with 152 additions and 78 deletions

View File

@ -213,21 +213,25 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
final EntityPersister persister = getPersister(); final EntityPersister persister = getPersister();
if ( success && isCachePutEnabled( persister, getSession() ) ) { if ( success && isCachePutEnabled( persister, getSession() ) ) {
final CacheKey ck = getSession().generateCacheKey( getId(), persister.getIdentifierType(), persister.getRootEntityName() ); final CacheKey ck = getSession().generateCacheKey( getId(), persister.getIdentifierType(), persister.getRootEntityName() );
try { final boolean put = cacheAfterInsert( persister, ck );
getSession().getEventListenerManager().cachePutStart();
final boolean put = persister.getCacheAccessStrategy().afterInsert( ck, cacheEntry, version );
if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) { if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
getSession().getFactory().getStatisticsImplementor() getSession().getFactory().getStatisticsImplementor()
.secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); .secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
} }
} }
postCommitInsert();
}
private boolean cacheAfterInsert(EntityPersister persister, CacheKey ck) {
try {
getSession().getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().afterInsert( ck, cacheEntry, version );
}
finally { finally {
getSession().getEventListenerManager().cachePutEnd(); getSession().getEventListenerManager().cachePutEnd();
} }
} }
postCommitInsert();
}
@Override @Override
protected boolean hasPostCommitEventListeners() { protected boolean hasPostCommitEventListeners() {

View File

@ -206,16 +206,11 @@ public final class EntityUpdateAction extends EntityAction {
final CacheEntry ce = persister.buildCacheEntry( instance,state, nextVersion, getSession() ); final CacheEntry ce = persister.buildCacheEntry( instance,state, nextVersion, getSession() );
cacheEntry = persister.getCacheEntryStructure().structure( ce ); cacheEntry = persister.getCacheEntryStructure().structure( ce );
try { final boolean put = cacheUpdate( persister, previousVersion, ck );
final boolean put = persister.getCacheAccessStrategy().update( ck, cacheEntry, nextVersion, previousVersion );
if ( put && factory.getStatistics().isStatisticsEnabled() ) { if ( put && factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); factory.getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
} }
} }
finally {
}
}
} }
session.getPersistenceContext().getNaturalIdHelper().manageSharedNaturalIdCrossReference( session.getPersistenceContext().getNaturalIdHelper().manageSharedNaturalIdCrossReference(
@ -233,6 +228,16 @@ public final class EntityUpdateAction extends EntityAction {
} }
} }
private boolean cacheUpdate(EntityPersister persister, Object previousVersion, CacheKey ck) {
try {
getSession().getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().update( ck, cacheEntry, nextVersion, previousVersion );
}
finally {
getSession().getEventListenerManager().cachePutEnd();
}
}
private boolean preUpdate() { private boolean preUpdate() {
boolean veto = false; boolean veto = false;
final EventListenerGroup<PreUpdateEventListener> listenerGroup = listenerGroup( EventType.PRE_UPDATE ); final EventListenerGroup<PreUpdateEventListener> listenerGroup = listenerGroup( EventType.PRE_UPDATE );
@ -315,18 +320,12 @@ public final class EntityUpdateAction extends EntityAction {
); );
if ( success && cacheEntry!=null /*!persister.isCacheInvalidationRequired()*/ ) { if ( success && cacheEntry!=null /*!persister.isCacheInvalidationRequired()*/ ) {
try { final boolean put = cacheAfterUpdate( persister, ck );
session.getEventListenerManager().cachePutStart();
final boolean put = persister.getCacheAccessStrategy().afterUpdate( ck, cacheEntry, nextVersion, previousVersion, lock );
if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) { if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
getSession().getFactory().getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); getSession().getFactory().getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
} }
} }
finally {
session.getEventListenerManager().cachePutEnd();
}
}
else { else {
persister.getCacheAccessStrategy().unlockItem( ck, lock ); persister.getCacheAccessStrategy().unlockItem( ck, lock );
} }
@ -334,5 +333,15 @@ public final class EntityUpdateAction extends EntityAction {
postCommitUpdate(); postCommitUpdate();
} }
private boolean cacheAfterUpdate(EntityPersister persister, CacheKey ck) {
try {
getSession().getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().afterUpdate( ck, cacheEntry, nextVersion, previousVersion, lock );
}
finally {
getSession().getEventListenerManager().cachePutEnd();
}
}
} }

View File

@ -0,0 +1,67 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.internal;
import java.io.Serializable;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.cache.spi.NaturalIdCacheKey;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
import org.hibernate.cache.spi.access.RegionAccessStrategy;
import org.hibernate.engine.spi.SessionImplementor;
/**
* @author Steve Ebersole
*/
public class CacheHelper {
public static Serializable fromSharedCache(
SessionImplementor session,
NaturalIdCacheKey cacheKey,
NaturalIdRegionAccessStrategy cacheAccessStrategy) {
return fromSharedCache( session, (Object) cacheKey, cacheAccessStrategy );
}
private static Serializable fromSharedCache(
SessionImplementor session,
Object cacheKey,
RegionAccessStrategy cacheAccessStrategy) {
Serializable cachedValue = null;
try {
session.getEventListenerManager().cacheGetStart();
cachedValue = (Serializable) cacheAccessStrategy.get( cacheKey, session.getTimestamp() );
}
finally {
session.getEventListenerManager().cacheGetEnd( cachedValue != null );
}
return cachedValue;
}
public static Serializable fromSharedCache(
SessionImplementor session,
CacheKey cacheKey,
RegionAccessStrategy cacheAccessStrategy) {
return fromSharedCache( session, (Object) cacheKey, cacheAccessStrategy );
}
}

View File

@ -259,7 +259,7 @@ public class NaturalIdXrefDelegate {
final NaturalIdCacheKey naturalIdCacheKey = new NaturalIdCacheKey( naturalIdValues, persister, session() ); final NaturalIdCacheKey naturalIdCacheKey = new NaturalIdCacheKey( naturalIdValues, persister, session() );
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy(); final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
pk = (Serializable) naturalIdCacheAccessStrategy.get( naturalIdCacheKey, session().getTimestamp() ); pk = CacheHelper.fromSharedCache( session(), naturalIdCacheKey, naturalIdCacheAccessStrategy );
// Found in second-level cache, store in session cache // Found in second-level cache, store in session cache
final SessionFactoryImplementor factory = session().getFactory(); final SessionFactoryImplementor factory = session().getFactory();

View File

@ -1693,7 +1693,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
switch ( source ) { switch ( source ) {
case LOAD: { case LOAD: {
if ( naturalIdCacheAccessStrategy.get( naturalIdCacheKey, session.getTimestamp() ) != null ) { if ( CacheHelper.fromSharedCache( session, naturalIdCacheKey, naturalIdCacheAccessStrategy ) != null ) {
// prevent identical re-cachings // prevent identical re-cachings
return; return;
} }
@ -1763,7 +1763,11 @@ public class StatefulPersistenceContext implements PersistenceContext {
public void doAfterTransactionCompletion(boolean success, SessionImplementor session) { public void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
naturalIdCacheAccessStrategy.unlockItem( previousCacheKey, removalLock ); naturalIdCacheAccessStrategy.unlockItem( previousCacheKey, removalLock );
if (success) { if (success) {
final boolean put = naturalIdCacheAccessStrategy.afterUpdate( naturalIdCacheKey, id, lock ); final boolean put = naturalIdCacheAccessStrategy.afterUpdate(
naturalIdCacheKey,
id,
lock
);
if ( put && factory.getStatistics().isStatisticsEnabled() ) { if ( put && factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor() factory.getStatisticsImplementor()

View File

@ -35,6 +35,7 @@ import org.jboss.logging.Logger;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.cache.spi.CacheKey; import org.hibernate.cache.spi.CacheKey;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.CacheHelper;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -218,12 +219,12 @@ public class BatchFetchQueue {
private boolean isCached(EntityKey entityKey, EntityPersister persister) { private boolean isCached(EntityKey entityKey, EntityPersister persister) {
if ( persister.hasCache() ) { if ( persister.hasCache() ) {
CacheKey key = context.getSession().generateCacheKey( final CacheKey key = context.getSession().generateCacheKey(
entityKey.getIdentifier(), entityKey.getIdentifier(),
persister.getIdentifierType(), persister.getIdentifierType(),
entityKey.getEntityName() entityKey.getEntityName()
); );
return persister.getCacheAccessStrategy().get( key, context.getSession().getTimestamp() ) != null; return CacheHelper.fromSharedCache( context.getSession(), key, persister.getCacheAccessStrategy() ) != null;
} }
return false; return false;
} }
@ -336,7 +337,7 @@ public class BatchFetchQueue {
persister.getKeyType(), persister.getKeyType(),
persister.getRole() persister.getRole()
); );
return persister.getCacheAccessStrategy().get( cacheKey, context.getSession().getTimestamp() ) != null; return CacheHelper.fromSharedCache( context.getSession(), cacheKey, persister.getCacheAccessStrategy() ) != null;
} }
return false; return false;
} }

View File

@ -29,6 +29,7 @@ import org.hibernate.HibernateException;
import org.hibernate.cache.spi.CacheKey; import org.hibernate.cache.spi.CacheKey;
import org.hibernate.cache.spi.entry.CollectionCacheEntry; import org.hibernate.cache.spi.entry.CollectionCacheEntry;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.CacheHelper;
import org.hibernate.engine.spi.CollectionEntry; import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -123,13 +124,8 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
if (!useCache) return false; if (!useCache) return false;
final SessionFactoryImplementor factory = source.getFactory(); final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = source.generateCacheKey( id, persister.getKeyType(), persister.getRole() ); final CacheKey ck = source.generateCacheKey( id, persister.getKeyType(), persister.getRole() );
final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
Object ce = null;
try {
source.getEventListenerManager().cacheGetStart();
ce = persister.getCacheAccessStrategy().get(ck, source.getTimestamp());
if ( factory.getStatistics().isStatisticsEnabled() ) { if ( factory.getStatistics().isStatisticsEnabled() ) {
if (ce == null) { if (ce == null) {
@ -141,10 +137,6 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
.secondLevelCacheHit( persister.getCacheAccessStrategy().getRegion().getName() ); .secondLevelCacheHit( persister.getCacheAccessStrategy().getRegion().getName() );
} }
} }
}
finally {
source.getEventListenerManager().cacheGetEnd( ce == null );
}
if ( ce == null ) { if ( ce == null ) {
return false; return false;

View File

@ -37,6 +37,7 @@ import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cache.spi.entry.CacheEntry; import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl; import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl; import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.engine.internal.CacheHelper;
import org.hibernate.engine.internal.TwoPhaseLoad; import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.internal.Versioning; import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
@ -547,11 +548,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
persister.getRootEntityName() persister.getRootEntityName()
); );
Object ce = null; final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
try {
source.getEventListenerManager().cacheGetStart();
ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
if ( factory.getStatistics().isStatisticsEnabled() ) { if ( factory.getStatistics().isStatisticsEnabled() ) {
if ( ce == null ) { if ( ce == null ) {
factory.getStatisticsImplementor().secondLevelCacheMiss( factory.getStatisticsImplementor().secondLevelCacheMiss(
@ -564,10 +561,6 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
); );
} }
} }
}
finally {
source.getEventListenerManager().cacheGetEnd( ce == null );
}
if ( ce == null ) { if ( ce == null ) {
// nothing was found in cache // nothing was found in cache

View File

@ -61,6 +61,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitHelper; import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.dialect.pagination.NoopLimitHandler; import org.hibernate.dialect.pagination.NoopLimitHandler;
import org.hibernate.engine.internal.CacheHelper;
import org.hibernate.engine.internal.TwoPhaseLoad; import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.jdbc.ColumnNameCache; import org.hibernate.engine.jdbc.ColumnNameCache;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
@ -1594,13 +1595,14 @@ public abstract class Loader {
// see if the entity defines reference caching, and if so use the cached reference (if one). // see if the entity defines reference caching, and if so use the cached reference (if one).
if ( persister.canUseReferenceCacheEntries() ) { if ( persister.canUseReferenceCacheEntries() ) {
final Object cachedEntry = persister.getCacheAccessStrategy().get( final Object cachedEntry = CacheHelper.fromSharedCache(
session,
session.generateCacheKey( session.generateCacheKey(
key.getIdentifier(), key.getIdentifier(),
persister.getEntityMetamodel().getEntityType(), persister.getEntityMetamodel().getEntityType(),
key.getEntityName() key.getEntityName()
), ),
session.getTimestamp() persister.getCacheAccessStrategy()
); );
if ( cachedEntry != null ) { if ( cachedEntry != null ) {
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( cachedEntry, factory ); CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( cachedEntry, factory );

View File

@ -64,6 +64,7 @@ import org.hibernate.cache.spi.entry.StructuredCacheEntry;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry; import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.dialect.lock.LockingStrategy; import org.hibernate.dialect.lock.LockingStrategy;
import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.internal.CacheHelper;
import org.hibernate.engine.internal.StatefulPersistenceContext; import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.internal.Versioning; import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
@ -1235,10 +1236,10 @@ public abstract class AbstractEntityPersister
} }
if ( hasCache() ) { if ( hasCache() ) {
CacheKey cacheKey = session.generateCacheKey( id, getIdentifierType(), getEntityName() ); final CacheKey cacheKey = session.generateCacheKey( id, getIdentifierType(), getEntityName() );
Object ce = getCacheAccessStrategy().get( cacheKey, session.getTimestamp() ); final Object ce = CacheHelper.fromSharedCache( session, cacheKey, getCacheAccessStrategy() );
if (ce!=null) { if ( ce != null ) {
CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory); final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory);
if ( !cacheEntry.areLazyPropertiesUnfetched() ) { if ( !cacheEntry.areLazyPropertiesUnfetched() ) {
//note early exit here: //note early exit here:
return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry ); return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry );
@ -4489,8 +4490,9 @@ public abstract class AbstractEntityPersister
// check to see if it is in the second-level cache // check to see if it is in the second-level cache
if ( hasCache() ) { if ( hasCache() ) {
CacheKey ck = session.generateCacheKey( id, getIdentifierType(), getRootEntityName() ); final CacheKey ck = session.generateCacheKey( id, getIdentifierType(), getRootEntityName() );
if ( getCacheAccessStrategy().get( ck, session.getTimestamp() ) != null ) { final Object ce = CacheHelper.fromSharedCache( session, ck, getCacheAccessStrategy() );
if ( ce != null ) {
return Boolean.FALSE; return Boolean.FALSE;
} }
} }