下面列出了怎么用org.hibernate.cache.spi.access.CollectionDataAccess的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public CollectionDataAccess generateCollectionAccess(CollectionDataCachingConfig accessConfig) {
final NavigableRole namedCollectionRole = accessConfig.getNavigableRole();
log.debugf( "Generating collection cache access : %s", namedCollectionRole );
switch ( accessConfig.getAccessType() ) {
case READ_ONLY: {
return generateReadOnlyCollectionAccess( accessConfig );
}
case READ_WRITE: {
return generateReadWriteCollectionAccess( accessConfig );
}
case NONSTRICT_READ_WRITE: {
return generateNonStrictReadWriteCollectionAccess( accessConfig );
}
case TRANSACTIONAL: {
return generateTransactionalCollectionDataAccess( accessConfig );
}
default: {
throw new IllegalArgumentException( "Unrecognized cache AccessType - " + accessConfig.getAccessType() );
}
}
}
private Map<NavigableRole, CollectionDataAccess> generateCollectionDataAccessMap(
DomainDataRegionConfig regionConfig) {
if ( regionConfig.getCollectionCaching().isEmpty() ) {
return Collections.emptyMap();
}
final Map<NavigableRole, CollectionDataAccess> accessMap = new ConcurrentHashMap<>();
for ( CollectionDataCachingConfig cachingConfig : regionConfig.getCollectionCaching() ) {
accessMap.computeIfAbsent(
cachingConfig.getNavigableRole(),
hierarchy -> generateCollectionAccess( cachingConfig )
);
}
return Collections.unmodifiableMap( accessMap );
}
@Override
public void evictCollectionData(String role, Serializable ownerIdentifier) {
final CollectionPersister collectionDescriptor = sessionFactory.getMetamodel()
.collectionPersister( role );
final CollectionDataAccess cacheAccess = collectionDescriptor.getCacheAccessStrategy();
if ( cacheAccess == null ) {
return;
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Evicting second-level cache: %s",
MessageHelper.collectionInfoString( collectionDescriptor, ownerIdentifier, sessionFactory )
);
}
final Object key = cacheAccess.generateCacheKey( ownerIdentifier, collectionDescriptor, sessionFactory, null );
cacheAccess.evict( key );
}
private void evictCachedCollections(Type[] types, Serializable id, EventSource source)
throws HibernateException {
for ( Type type : types ) {
if ( type.isCollectionType() ) {
CollectionPersister collectionPersister = source.getFactory().getMetamodel().collectionPersister( ( (CollectionType) type ).getRole() );
if ( collectionPersister.hasCache() ) {
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
id,
collectionPersister,
source.getFactory(),
source.getTenantIdentifier()
);
final SoftLock lock = cache.lockItem( source, ck, null );
cache.remove( source, ck );
source.getActionQueue().registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
}
}
else if ( type.isComponentType() ) {
CompositeType actype = (CompositeType) type;
evictCachedCollections( actype.getSubtypes(), id, source );
}
}
}
@Override
public final void beforeExecutions() throws CacheException {
// we need to obtain the lock before any actions are executed, since this may be an inverse="true"
// bidirectional association and it is one of the earlier entity actions which actually updates
// the database (this action is responsible for second-level cache invalidation only)
if ( persister.hasCache() ) {
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
key,
persister,
session.getFactory(),
session.getTenantIdentifier()
);
final SoftLock lock = cache.lockItem( session, ck, null );
// the old behavior used key as opposed to getKey()
afterTransactionProcess = new CacheCleanupProcess( key, persister, lock );
}
}
private void evictCachedCollections(Type[] types, Serializable id, EventSource source)
throws HibernateException {
final ActionQueue actionQueue = source.getActionQueue();
final SessionFactoryImplementor factory = source.getFactory();
final MetamodelImplementor metamodel = factory.getMetamodel();
for ( Type type : types ) {
if ( type.isCollectionType() ) {
CollectionPersister collectionPersister = metamodel.collectionPersister( ( (CollectionType) type ).getRole() );
if ( collectionPersister.hasCache() ) {
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
id,
collectionPersister,
factory,
source.getTenantIdentifier()
);
final SoftLock lock = cache.lockItem( source, ck, null );
cache.remove( source, ck );
actionQueue.registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
}
}
else if ( type.isComponentType() ) {
CompositeType actype = (CompositeType) type;
evictCachedCollections( actype.getSubtypes(), id, source );
}
}
}
@Override
@SuppressWarnings( {"unchecked"})
public CollectionPersister createCollectionPersister(
Collection collectionBinding,
CollectionDataAccess cacheAccessStrategy,
PersisterCreationContext creationContext) throws HibernateException {
// If the metadata for the collection specified an explicit persister class, use it
Class<? extends CollectionPersister> persisterClass = collectionBinding.getCollectionPersisterClass();
if ( persisterClass == null ) {
// Otherwise, use the persister class indicated by the PersisterClassResolver service
persisterClass = serviceRegistry.getService( PersisterClassResolver.class )
.getCollectionPersisterClass( collectionBinding );
}
return createCollectionPersister( persisterClass, collectionBinding, cacheAccessStrategy, creationContext );
}
public OneToManyPersister(
Collection collectionBinding,
CollectionDataAccess cacheAccessStrategy,
PersisterCreationContext creationContext) throws MappingException, CacheException {
super( collectionBinding, cacheAccessStrategy, creationContext );
cascadeDeleteEnabled = collectionBinding.getKey().isCascadeDeleteEnabled()
&& creationContext.getSessionFactory().getDialect().supportsCascadeDelete();
keyIsNullable = collectionBinding.getKey().isNullable();
keyIsUpdateable = collectionBinding.getKey().isUpdateable();
}
private boolean isCached(Serializable collectionKey, CollectionPersister persister) {
SharedSessionContractImplementor session = context.getSession();
if ( session.getCacheMode().isGetEnabled() && persister.hasCache() ) {
CollectionDataAccess cache = persister.getCacheAccessStrategy();
Object cacheKey = cache.generateCacheKey(
collectionKey,
persister,
session.getFactory(),
session.getTenantIdentifier()
);
return CacheHelper.fromSharedCache( session, cacheKey, cache ) != null;
}
return false;
}
private CollectionDataAccess generateReadOnlyCollectionAccess(CollectionDataCachingConfig accessConfig) {
return new CollectionReadOnlyAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
private CollectionDataAccess generateReadWriteCollectionAccess(CollectionDataCachingConfig accessConfig) {
return new CollectionReadWriteAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
private CollectionDataAccess generateNonStrictReadWriteCollectionAccess(CollectionDataCachingConfig accessConfig) {
return new CollectionNonStrictReadWriteAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
@Override
public CollectionDataAccess getCollectionDataAccess(NavigableRole collectionRole) {
final CollectionDataAccess access = collectionDataAccessMap.get( collectionRole );
if ( access == null ) {
throw new IllegalArgumentException( "Caching was not configured for collection : " + collectionRole.getFullPath() );
}
return access;
}
@Override
protected CollectionDataAccess generateTransactionalCollectionDataAccess(CollectionDataCachingConfig accessConfig) {
return new CollectionTransactionAccess(
this,
getEffectiveKeysFactory(),
getCacheStorageAccess(),
accessConfig
);
}
@Override
public boolean containsCollection(String role, Serializable ownerIdentifier) {
final CollectionPersister collectionDescriptor = sessionFactory.getMetamodel()
.collectionPersister( role );
final CollectionDataAccess cacheAccess = collectionDescriptor.getCacheAccessStrategy();
if ( cacheAccess == null ) {
return false;
}
final Object key = cacheAccess.generateCacheKey( ownerIdentifier, collectionDescriptor, sessionFactory, null );
return cacheAccess.contains( key );
}
private void evictCollectionData(NavigableRole navigableRole, CollectionDataAccess cacheAccess) {
if ( cacheAccess == null ) {
return;
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Evicting second-level cache: %s", navigableRole.getFullPath() );
}
cacheAccess.evictAll();
}
protected final void evict() throws CacheException {
if ( persister.hasCache() ) {
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
key,
persister,
session.getFactory(),
session.getTenantIdentifier()
);
cache.remove( session, ck);
}
}
@Override
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(
key,
persister,
session.getFactory(),
session.getTenantIdentifier()
);
cache.unlockItem( session, ck, lock );
}
private CollectionCleanup(
CollectionDataAccess cacheAccess,
SharedSessionContractImplementor session) {
this.cacheAccess = cacheAccess;
this.cacheLock = cacheAccess.lockRegion();
cacheAccess.removeAll( session );
}
/** {@inheritDoc} */
@Override protected CollectionDataAccess generateCollectionAccess(CollectionDataCachingConfig cachingCfg) {
HibernateCacheProxy cache = stgyFactory.regionCache(getName());
AccessType accessType = cachingCfg.getAccessType();
Ignite ignite = stgyFactory.node();
switch (accessType) {
case READ_ONLY:
HibernateAccessStrategyAdapter readOnlyStgy =
stgyFactory.createReadOnlyStrategy(cache);
return new IgniteCollectionDataAccess(readOnlyStgy, accessType, getRegionFactory(),
this, ignite, cache);
case NONSTRICT_READ_WRITE:
HibernateAccessStrategyAdapter nonStrictReadWriteStgy =
stgyFactory.createNonStrictReadWriteStrategy(cache);
return new IgniteCollectionDataAccess(nonStrictReadWriteStgy, accessType, getRegionFactory(),
this, ignite, cache);
case READ_WRITE:
HibernateAccessStrategyAdapter readWriteStgy =
stgyFactory.createReadWriteStrategy(cache);
return new IgniteCollectionDataAccess(readWriteStgy, accessType, getRegionFactory(),
this, ignite, cache);
case TRANSACTIONAL:
HibernateAccessStrategyAdapter transactionalStgy =
stgyFactory.createTransactionalStrategy(cache);
return new IgniteCollectionDataAccess(transactionalStgy, accessType, getRegionFactory(),
this, ignite, cache);
default:
throw new IllegalArgumentException("Unknown Hibernate access type: " + accessType);
}
}
public ReactiveOneToManyPersister(Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, PersisterCreationContext creationContext) throws MappingException, CacheException {
super( collectionBinding, cacheAccessStrategy, creationContext );
}
/**
* Try to initialize a collection from the cache
*
* @param id The id of the collection to initialize
* @param persister The collection persister
* @param collection The collection to initialize
* @param source The originating session
*
* @return true if we were able to initialize the collection from the cache;
* false otherwise.
*/
private boolean initializeCollectionFromCache(
Serializable id,
CollectionPersister persister,
PersistentCollection collection,
SessionImplementor source) {
if ( source.getLoadQueryInfluencers().hasEnabledFilters() && persister.isAffectedByEnabledFilters( source ) ) {
LOG.trace( "Disregarding cached version (if any) of collection due to enabled filters" );
return false;
}
final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled();
if ( !useCache ) {
return false;
}
final SessionFactoryImplementor factory = source.getFactory();
final CollectionDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
final Object ck = cacheAccessStrategy.generateCacheKey( id, persister, factory, source.getTenantIdentifier() );
final Object ce = CacheHelper.fromSharedCache( source, ck, cacheAccessStrategy );
final StatisticsImplementor statistics = factory.getStatistics();
if ( statistics.isStatisticsEnabled() ) {
if ( ce == null ) {
statistics.collectionCacheMiss( persister.getNavigableRole(), cacheAccessStrategy.getRegion().getName() );
}
else {
statistics.collectionCacheHit( persister.getNavigableRole(), cacheAccessStrategy.getRegion().getName() );
}
}
if ( ce == null ) {
return false;
}
CollectionCacheEntry cacheEntry = (CollectionCacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
cacheEntry.assemble( collection, persister, persistenceContext.getCollectionOwner( id, persister ) );
persistenceContext.getCollectionEntry( collection ).postInitialize( collection );
return true;
}
public BasicCollectionPersister(
Collection collectionBinding,
CollectionDataAccess cacheAccessStrategy,
PersisterCreationContext creationContext) throws MappingException, CacheException {
super( collectionBinding, cacheAccessStrategy, creationContext );
}
@Override
public CollectionDataAccess getCacheAccessStrategy() {
return cacheAccessStrategy;
}
/**
* Add the collection to the second-level cache
*
* @param lce The entry representing the collection to add
* @param persister The persister
*/
private void addCollectionToCache(LoadingCollectionEntry lce, CollectionPersister persister) {
final SharedSessionContractImplementor session = getLoadContext().getPersistenceContext().getSession();
final SessionFactoryImplementor factory = session.getFactory();
final boolean debugEnabled = LOG.isDebugEnabled();
if ( debugEnabled ) {
LOG.debugf( "Caching collection: %s", MessageHelper.collectionInfoString( persister, lce.getCollection(), lce.getKey(), session ) );
}
if ( !session.getLoadQueryInfluencers().getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters( session ) ) {
// some filters affecting the collection are enabled on the session, so do not do the put into the cache.
if ( debugEnabled ) {
LOG.debug( "Refusing to add to cache due to enabled filters" );
}
// todo : add the notion of enabled filters to the cache key to differentiate filtered collections from non-filtered;
// DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from
// cache with enabled filters).
// EARLY EXIT!!!!!
return;
}
final Object version;
if ( persister.isVersioned() ) {
Object collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner( lce.getKey(), persister );
if ( collectionOwner == null ) {
// generally speaking this would be caused by the collection key being defined by a property-ref, thus
// the collection key and the owner key would not match up. In this case, try to use the key of the
// owner instance associated with the collection itself, if one. If the collection does already know
// about its owner, that owner should be the same instance as associated with the PC, but we do the
// resolution against the PC anyway just to be safe since the lookup should not be costly.
if ( lce.getCollection() != null ) {
final Object linkedOwner = lce.getCollection().getOwner();
if ( linkedOwner != null ) {
final Serializable ownerKey = persister.getOwnerEntityPersister().getIdentifier( linkedOwner, session );
collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner( ownerKey, persister );
}
}
if ( collectionOwner == null ) {
throw new HibernateException(
"Unable to resolve owner of loading collection [" +
MessageHelper.collectionInfoString( persister, lce.getCollection(), lce.getKey(), session ) +
"] for second level caching"
);
}
}
version = getLoadContext().getPersistenceContext().getEntry( collectionOwner ).getVersion();
}
else {
version = null;
}
final CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
final CollectionDataAccess cacheAccess = persister.getCacheAccessStrategy();
final Object cacheKey = cacheAccess.generateCacheKey(
lce.getKey(),
persister,
session.getFactory(),
session.getTenantIdentifier()
);
boolean isPutFromLoad = true;
if ( persister.getElementType().isAssociationType() ) {
for ( Serializable id : entry.getState() ) {
EntityPersister entityPersister = ( (QueryableCollection) persister ).getElementPersister();
if ( session.getPersistenceContext().wasInsertedDuringTransaction( entityPersister, id ) ) {
isPutFromLoad = false;
break;
}
}
}
// CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad
if (isPutFromLoad) {
try {
session.getEventListenerManager().cachePutStart();
final boolean put = cacheAccess.putFromLoad(
session,
cacheKey,
persister.getCacheEntryStructure().structure( entry ),
version,
factory.getSessionFactoryOptions().isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH
);
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatistics().collectionCachePut(
persister.getNavigableRole(),
persister.getCacheAccessStrategy().getRegion().getName()
);
}
}
finally {
session.getEventListenerManager().cachePutEnd();
}
}
}
@SuppressWarnings({"WeakerAccess", "unused"})
protected CollectionDataAccess generateTransactionalCollectionDataAccess(CollectionDataCachingConfig accessConfig) {
throw generateTransactionalNotSupportedException();
}
protected void releaseDataAccess(CollectionDataAccess cacheAccess) {
if ( Destructible.class.isInstance( cacheAccess ) ) {
( (Destructible) cacheAccess ).destroy();
}
}
@Override
public CollectionDataAccess getCollectionRegionAccess(NavigableRole collectionRole) {
return null;
}
@Override
public void prime(Set<DomainDataRegionConfig> cacheRegionConfigs) {
for ( DomainDataRegionConfig regionConfig : cacheRegionConfigs ) {
final DomainDataRegion region = getRegionFactory().buildDomainDataRegion( regionConfig, this );
regionsByName.put( region.getName(), region );
if ( ! Objects.equals( region.getName(), regionConfig.getRegionName() ) ) {
throw new HibernateException(
String.format(
Locale.ROOT,
"Region [%s] returned from RegionFactory [%s] was named differently than requested name. Expecting `%s`, but found `%s`",
region,
getRegionFactory().getClass().getName(),
regionConfig.getRegionName(),
region.getName()
)
);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Entity caching
for ( EntityDataCachingConfig entityAccessConfig : regionConfig.getEntityCaching() ) {
final EntityDataAccess entityDataAccess = entityAccessMap.put(
entityAccessConfig.getNavigableRole(),
region.getEntityDataAccess( entityAccessConfig.getNavigableRole() )
);
legacySecondLevelCacheNames.add(
StringHelper.qualifyConditionally(
getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix(),
region.getName()
)
);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Natural-id caching
if ( regionConfig.getNaturalIdCaching().isEmpty() ) {
legacyNaturalIdAccessesForRegion.put( region.getName(), Collections.emptySet() );
}
else {
final HashSet<NaturalIdDataAccess> accesses = new HashSet<>();
for ( NaturalIdDataCachingConfig naturalIdAccessConfig : regionConfig.getNaturalIdCaching() ) {
final NaturalIdDataAccess naturalIdDataAccess = naturalIdAccessMap.put(
naturalIdAccessConfig.getNavigableRole(),
region.getNaturalIdDataAccess( naturalIdAccessConfig.getNavigableRole() )
);
accesses.add( naturalIdDataAccess );
}
legacyNaturalIdAccessesForRegion.put( region.getName(), accesses );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Collection caching
for ( CollectionDataCachingConfig collectionAccessConfig : regionConfig.getCollectionCaching() ) {
final CollectionDataAccess collectionDataAccess = collectionAccessMap.put(
collectionAccessConfig.getNavigableRole(),
region.getCollectionDataAccess( collectionAccessConfig.getNavigableRole() )
);
legacySecondLevelCacheNames.add(
StringHelper.qualifyConditionally(
getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix(),
region.getName()
)
);
}
}
}
@Override
public CollectionDataAccess getCollectionRegionAccess(NavigableRole collectionRole) {
return collectionAccessMap.get( collectionRole );
}