下面列出了怎么用org.hibernate.cache.spi.access.EntityDataAccess的API类实例代码及写法,或者点击链接到github查看源代码。
@SuppressWarnings("unchecked")
private boolean determineCanReadFromCache(PersistentClass persistentClass, EntityDataAccess cacheAccessStrategy) {
if ( cacheAccessStrategy == null ) {
return false;
}
if ( persistentClass.isCached() ) {
return true;
}
final Iterator<Subclass> subclassIterator = persistentClass.getSubclassIterator();
while ( subclassIterator.hasNext() ) {
final Subclass subclass = subclassIterator.next();
if ( subclass.isCached() ) {
return true;
}
}
return false;
}
@Override
@SuppressWarnings( {"unchecked"})
public EntityPersister createEntityPersister(
PersistentClass entityBinding,
EntityDataAccess entityCacheAccessStrategy,
NaturalIdDataAccess naturalIdCacheAccessStrategy,
PersisterCreationContext creationContext) throws HibernateException {
// If the metadata for the entity specified an explicit persister class, use it...
Class<? extends EntityPersister> persisterClass = entityBinding.getEntityPersisterClass();
if ( persisterClass == null ) {
// Otherwise, use the persister class indicated by the PersisterClassResolver service
persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( entityBinding );
}
return createEntityPersister(
persisterClass,
entityBinding,
entityCacheAccessStrategy,
naturalIdCacheAccessStrategy,
creationContext
);
}
@Override
public EntityDataAccess generateEntityAccess(EntityDataCachingConfig entityAccessConfig) {
final NavigableRole namedEntityRole = entityAccessConfig.getNavigableRole();
final AccessType accessType = entityAccessConfig.getAccessType();
log.debugf( "Generating entity cache access [%s] : %s", accessType.getExternalName(), namedEntityRole );
switch ( accessType ) {
case READ_ONLY: {
return generateReadOnlyEntityAccess( entityAccessConfig );
}
case READ_WRITE: {
return generateReadWriteEntityAccess( entityAccessConfig );
}
case NONSTRICT_READ_WRITE: {
return generateNonStrictReadWriteEntityAccess( entityAccessConfig );
}
case TRANSACTIONAL: {
return generateTransactionalEntityDataAccess( entityAccessConfig );
}
default: {
throw new IllegalArgumentException( "Unrecognized cache AccessType - " + accessType );
}
}
}
private Map<NavigableRole, EntityDataAccess> generateEntityDataAccessMap(
DomainDataRegionConfig regionConfig) {
if ( regionConfig.getEntityCaching().isEmpty() ) {
return Collections.emptyMap();
}
final Map<NavigableRole, EntityDataAccess> accessMap = new ConcurrentHashMap<>();
for ( EntityDataCachingConfig entityAccessConfig : regionConfig.getEntityCaching() ) {
accessMap.computeIfAbsent(
entityAccessConfig.getNavigableRole(),
hierarchy -> generateEntityAccess( entityAccessConfig )
);
}
return Collections.unmodifiableMap( accessMap );
}
@Override
public void evictEntityData(String entityName, Serializable identifier) {
final EntityPersister entityDescriptor = sessionFactory.getMetamodel().entityPersister( entityName );
final EntityDataAccess cacheAccess = entityDescriptor.getCacheAccessStrategy();
if ( cacheAccess == null ) {
return;
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Evicting second-level cache: %s",
MessageHelper.infoString( entityDescriptor, identifier, sessionFactory )
);
}
final Object key = cacheAccess.generateCacheKey( identifier, entityDescriptor, sessionFactory, null );
cacheAccess.evict( key );
}
@Override
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
final EntityPersister persister = getPersister();
if ( success && isCachePutEnabled( persister, getSession() ) ) {
final EntityDataAccess cache = persister.getCacheAccessStrategy();
SessionFactoryImplementor factory = session.getFactory();
final Object ck = cache.generateCacheKey( getId(), persister, factory, session.getTenantIdentifier() );
final boolean put = cacheAfterInsert( cache, ck );
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatistics().entityCachePut(
StatsHelper.INSTANCE.getRootEntityRole( persister ),
cache.getRegion().getName()
);
}
}
postCommitInsert( success );
}
public ReactiveSingleTableEntityPersister(
PersistentClass persistentClass,
EntityDataAccess cacheAccessStrategy,
NaturalIdDataAccess naturalIdRegionAccessStrategy,
PersisterCreationContext creationContext) throws HibernateException {
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext );
}
public ReactiveJoinedSubclassEntityPersister(
PersistentClass persistentClass,
EntityDataAccess cacheAccessStrategy,
NaturalIdDataAccess naturalIdRegionAccessStrategy,
PersisterCreationContext creationContext) throws HibernateException {
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext );
}
public ReactiveUnionSubclassEntityPersister(
PersistentClass persistentClass,
EntityDataAccess cacheAccessStrategy,
NaturalIdDataAccess naturalIdRegionAccessStrategy,
PersisterCreationContext creationContext) throws HibernateException {
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext );
}
private boolean determineCanWriteToCache(PersistentClass persistentClass, EntityDataAccess cacheAccessStrategy) {
if ( cacheAccessStrategy == null ) {
return false;
}
return persistentClass.isCached();
}
private boolean isCached(EntityKey entityKey, EntityPersister persister) {
final SharedSessionContractImplementor session = context.getSession();
if ( context.getSession().getCacheMode().isGetEnabled() && persister.canReadFromCache() ) {
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object key = cache.generateCacheKey(
entityKey.getIdentifier(),
persister,
session.getFactory(),
session.getTenantIdentifier()
);
return CacheHelper.fromSharedCache( session, key, cache ) != null;
}
return false;
}
@SuppressWarnings("WeakerAccess")
protected EntityDataAccess generateReadOnlyEntityAccess(EntityDataCachingConfig accessConfig) {
return new EntityReadOnlyAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
@SuppressWarnings("WeakerAccess")
protected EntityDataAccess generateReadWriteEntityAccess(EntityDataCachingConfig accessConfig) {
return new EntityReadWriteAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
@SuppressWarnings("WeakerAccess")
protected EntityDataAccess generateNonStrictReadWriteEntityAccess(EntityDataCachingConfig accessConfig) {
return new EntityNonStrictReadWriteAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
@Override
public EntityDataAccess getEntityDataAccess(NavigableRole rootEntityRole) {
final EntityDataAccess access = entityDataAccessMap.get( rootEntityRole );
if ( access == null ) {
throw new IllegalArgumentException( "Caching was not configured for entity : " + rootEntityRole.getFullPath() );
}
return access;
}
@Override
protected EntityDataAccess generateTransactionalEntityDataAccess(EntityDataCachingConfig entityAccessConfig) {
return new EntityTransactionalAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
entityAccessConfig
);
}
@Override
public boolean containsEntity(String entityName, Serializable identifier) {
final EntityPersister entityDescriptor = sessionFactory.getMetamodel().entityPersister( entityName );
final EntityDataAccess cacheAccess = entityDescriptor.getCacheAccessStrategy();
if ( cacheAccess == null ) {
return false;
}
final Object key = cacheAccess.generateCacheKey( identifier, entityDescriptor, sessionFactory, null );
return cacheAccess.contains( key );
}
private void evictEntityData(NavigableRole navigableRole, EntityDataAccess cacheAccess) {
if ( cacheAccess == null ) {
return;
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Evicting entity cache: %s", navigableRole.getFullPath() );
}
cacheAccess.evictAll();
}
/**
* If the class to be loaded has been configured with a cache, then lock
* given id in that cache and then perform the load.
*
* @param event The initiating load request event
* @param persister The persister corresponding to the entity to be loaded
* @param keyToLoad The key of the entity to be loaded
* @param options The defined load options
* @param source The originating session
*
* @return The loaded entity
*
* @throws HibernateException
*/
private Object lockAndLoad(
final LoadEvent event,
final EntityPersister persister,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options,
final SessionImplementor source) {
SoftLock lock = null;
final Object ck;
final EntityDataAccess cache = persister.getCacheAccessStrategy();
if ( persister.canWriteToCache() ) {
ck = cache.generateCacheKey(
event.getEntityId(),
persister,
source.getFactory(),
source.getTenantIdentifier()
);
lock = persister.getCacheAccessStrategy().lockItem( source, ck, null );
}
else {
ck = null;
}
Object entity;
try {
entity = load( event, persister, keyToLoad, options );
}
finally {
if ( persister.canWriteToCache() ) {
cache.unlockItem( source, ck, lock );
}
}
return event.getSession().getPersistenceContext().proxyFor( persister, keyToLoad, entity );
}
private Object getFromSharedCache(
final LoadEvent event,
final EntityPersister persister,
SessionImplementor source ) {
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
event.getEntityId(),
persister,
source.getFactory(),
source.getTenantIdentifier()
);
final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
if ( ce == null ) {
source.getFactory().getStatistics().entityCacheMiss(
StatsHelper.INSTANCE.getRootEntityRole( persister ),
cache.getRegion().getName()
);
}
else {
source.getFactory().getStatistics().entityCacheHit(
StatsHelper.INSTANCE.getRootEntityRole( persister ),
cache.getRegion().getName()
);
}
}
return ce;
}
@Override
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
EntityPersister entityPersister = getPersister();
if ( entityPersister.canWriteToCache() ) {
EntityDataAccess cache = entityPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
getId(),
entityPersister,
session.getFactory(),
session.getTenantIdentifier()
);
cache.unlockItem( session, ck, lock );
}
postCommitDelete( success );
}
private boolean cacheAfterInsert(EntityDataAccess cache, Object ck) {
SharedSessionContractImplementor session = getSession();
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
try {
eventListenerManager.cachePutStart();
return cache.afterInsert( session, ck, cacheEntry, version );
}
finally {
eventListenerManager.cachePutEnd();
}
}
/**
* Constructs an action to cleanup "affected cache regions" based on the
* affected entity persisters. The affected regions are defined as the
* region (if any) of the entity persisters themselves, plus the
* collection regions for any collection in which those entity
* persisters participate as elements/keys/etc.
*
* @param session The session to which this request is tied.
* @param affectedQueryables The affected entity persisters.
*/
public BulkOperationCleanupAction(SharedSessionContractImplementor session, Queryable... affectedQueryables) {
final SessionFactoryImplementor factory = session.getFactory();
final LinkedHashSet<String> spacesList = new LinkedHashSet<>();
for ( Queryable persister : affectedQueryables ) {
spacesList.addAll( Arrays.asList( (String[]) persister.getQuerySpaces() ) );
if ( persister.canWriteToCache() ) {
final EntityDataAccess entityDataAccess = persister.getCacheAccessStrategy();
if ( entityDataAccess != null ) {
entityCleanups.add( new EntityCleanup( entityDataAccess, session ) );
}
}
if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
naturalIdCleanups.add(
new NaturalIdCleanup( persister.getNaturalIdCacheAccessStrategy(), session )
);
}
final Set<String> roles = factory.getMetamodel().getCollectionRolesByEntityParticipant( persister.getEntityName() );
if ( roles != null ) {
for ( String role : roles ) {
final CollectionPersister collectionPersister = factory.getMetamodel().collectionPersister( role );
if ( collectionPersister.hasCache() ) {
collectionCleanups.add(
new CollectionCleanup(
collectionPersister.getCacheAccessStrategy(),
session
)
);
}
}
}
}
this.affectedTableSpaces = spacesList.toArray( new String[ spacesList.size() ] );
}
private EntityCleanup(
EntityDataAccess cacheAccess,
SharedSessionContractImplementor session) {
this.cacheAccess = cacheAccess;
this.cacheLock = cacheAccess.lockRegion();
cacheAccess.removeAll( session );
}
@Override
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws CacheException {
final EntityPersister persister = getPersister();
if ( persister.canWriteToCache() ) {
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
getId(),
persister,
session.getFactory(),
session.getTenantIdentifier()
);
if ( success &&
cacheEntry != null &&
!persister.isCacheInvalidationRequired() &&
session.getCacheMode().isPutEnabled() ) {
final boolean put = cacheAfterUpdate( cache, ck );
if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatistics().entityCachePut(
StatsHelper.INSTANCE.getRootEntityRole( persister ),
getPersister().getCacheAccessStrategy().getRegion().getName()
);
}
}
else {
cache.unlockItem(session, ck, lock );
}
}
postCommitUpdate( success );
}
private boolean cacheAfterUpdate(EntityDataAccess cache, Object ck) {
final SharedSessionContractImplementor session = getSession();
SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
try {
eventListenerManager.cachePutStart();
return cache.afterUpdate( session, ck, cacheEntry, nextVersion, previousVersion, lock );
}
finally {
eventListenerManager.cachePutEnd();
}
}
/** {@inheritDoc} */
@Override protected EntityDataAccess generateEntityAccess(EntityDataCachingConfig entityAccessCfg) {
AccessType accessType = entityAccessCfg.getAccessType();
Ignite ignite = stgyFactory.node();
switch (accessType) {
case READ_ONLY:
HibernateAccessStrategyAdapter readOnlyStgy =
stgyFactory.createReadOnlyStrategy(cache);
return new IgniteEntityDataAccess(readOnlyStgy, accessType, getRegionFactory(),
this, ignite, cache);
case NONSTRICT_READ_WRITE:
HibernateAccessStrategyAdapter nonStrictReadWriteStgy =
stgyFactory.createNonStrictReadWriteStrategy(cache);
return new IgniteEntityDataAccess(nonStrictReadWriteStgy, accessType, getRegionFactory(),
this, ignite, cache);
case READ_WRITE:
HibernateAccessStrategyAdapter readWriteStgy =
stgyFactory.createReadWriteStrategy(cache);
return new IgniteEntityDataAccess(readWriteStgy, accessType, getRegionFactory(),
this, ignite, cache);
case TRANSACTIONAL:
HibernateAccessStrategyAdapter transactionalStgy =
stgyFactory.createTransactionalStrategy(cache);
return new IgniteEntityDataAccess(transactionalStgy, accessType, getRegionFactory(),
this, ignite, cache);
default:
throw new IllegalArgumentException("Unknown Hibernate access type: " + accessType);
}
}
@Override
public CompletionStage<Void> reactiveExecute() throws HibernateException {
return reactiveNullifyTransientReferencesIfNotAlready().thenCompose( v-> {
EntityPersister persister = getPersister();
final SharedSessionContractImplementor session = getSession();
final Object instance = getInstance();
final Serializable id = getId();
// FIXME: It needs to become async
final boolean veto = preInsert();
// Don't need to lock the cache here, since if someone
// else inserted the same pk first, the insert would fail
CompletionStage<Void> insertStage;
if ( !veto ) {
insertStage = ((ReactiveEntityPersister) persister)
.insertReactive( id, getState(), instance, session )
.thenApply( res -> {
PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entry = persistenceContext.getEntry( instance );
if ( entry == null ) {
throw new AssertionFailure( "possible non-threadsafe access to session" );
}
entry.postInsert( getState() );
if ( persister.hasInsertGeneratedProperties() ) {
persister.processInsertGeneratedProperties( id, instance, getState(), session );
if ( persister.isVersionPropertyGenerated() ) {
setVersion( Versioning.getVersion( getState(), persister ) );
}
entry.postUpdate( instance, getState(), getVersion() );
}
persistenceContext.registerInsertedKey( persister, getId() );
return null;
} );
}
else {
insertStage = CompletionStages.nullFuture();
}
return insertStage.thenApply( res -> {
final SessionFactoryImplementor factory = session.getFactory();
if ( isCachePutEnabled( persister, session ) ) {
final CacheEntry ce = persister.buildCacheEntry(
instance,
getState(),
getVersion(),
session
);
setCacheEntry( persister.getCacheEntryStructure().structure( ce ) );
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey( id, persister, factory, session.getTenantIdentifier() );
final boolean put = cacheInsert( persister, ck );
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatistics().entityCachePut(
persister.getNavigableRole(),
persister.getCacheAccessStrategy().getRegion().getName()
);
}
}
handleNaturalIdPostSaveNotifications( id );
postInsert();
if ( factory.getStatistics().isStatisticsEnabled() && !veto ) {
factory.getStatistics().insertEntity( getEntityName() );
}
markExecuted();
return null;
} );
} );
}
@Override
public CompletionStage<Void> reactiveExecute() throws HibernateException {
final Serializable id = getId();
final EntityPersister persister = getPersister();
final SharedSessionContractImplementor session = getSession();
final Object instance = getInstance();
final boolean veto = preDelete();
Object version = getVersion();
if ( persister.isVersionPropertyGenerated() ) {
// we need to grab the version value from the entity, otherwise
// we have issues with generated-version entities that may have
// multiple actions queued during the same flush
version = persister.getVersion( instance );
}
final Object ck;
if ( persister.canWriteToCache() ) {
final EntityDataAccess cache = persister.getCacheAccessStrategy();
ck = cache.generateCacheKey( id, persister, session.getFactory(), session.getTenantIdentifier() );
setLock( cache.lockItem( session, ck, version ) );
}
else {
ck = null;
}
CompletionStage<?> deleteStep = CompletionStages.nullFuture();
if ( !isCascadeDeleteEnabled() && !veto ) {
deleteStep = ((ReactiveEntityPersister) persister).deleteReactive( id, version, instance, session );
}
return deleteStep.thenAccept( deleteAR -> {
//postDelete:
// After actually deleting a row, record the fact that the instance no longer
// exists on the database (needed for identity-column key generation), and
// remove it from the session cache
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
final EntityEntry entry = persistenceContext.removeEntry( instance );
if ( entry == null ) {
throw new AssertionFailure( "possible non-threadsafe access to session" );
}
entry.postDelete();
persistenceContext.removeEntity( entry.getEntityKey() );
persistenceContext.removeProxy( entry.getEntityKey() );
if ( persister.canWriteToCache() ) {
persister.getCacheAccessStrategy().remove( session, ck );
}
persistenceContext.getNaturalIdHelper().removeSharedNaturalIdCrossReference(
persister,
id,
getNaturalIdValues()
);
postDelete();
final StatisticsImplementor statistics = getSession().getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() && !veto ) {
statistics.deleteEntity( getPersister().getEntityName() );
}
} );
}
/**
* If the class to be loaded has been configured with a cache, then lock
* given id in that cache and then perform the load.
*
* @param event The initiating load request event
* @param persister The persister corresponding to the entity to be loaded
* @param keyToLoad The key of the entity to be loaded
* @param options The defined load options
* @param source The originating session
*
* @return The loaded entity
*/
private CompletionStage<Object> lockAndLoad(
final LoadEvent event,
final EntityPersister persister,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options,
final SessionImplementor source) {
final SoftLock lock;
final Object ck;
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final boolean canWriteToCache = persister.canWriteToCache();
if ( canWriteToCache ) {
ck = cache.generateCacheKey(
event.getEntityId(),
persister,
source.getFactory(),
source.getTenantIdentifier()
);
lock = cache.lockItem( source, ck, null );
}
else {
ck = null;
lock = null;
}
try {
return load( event, persister, keyToLoad, options )
.whenComplete( (v, x) -> {
if ( canWriteToCache ) {
cache.unlockItem( source, ck, lock );
}
} )
.thenApply( entity -> source.getPersistenceContextInternal().proxyFor( persister, keyToLoad, entity ) );
}
catch (HibernateException he) {
//in case load() throws an exception
if ( canWriteToCache ) {
cache.unlockItem( source, ck, lock );
}
throw he;
}
}