All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.cache.spi.support.AbstractDomainDataRegion Maven / Gradle / Ivy

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later
 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
 */
package org.hibernate.cache.spi.support;

import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.hibernate.cache.CacheException;
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
import org.hibernate.cache.spi.CacheKeysFactory;
import org.hibernate.cache.spi.DomainDataRegion;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.access.CollectionDataAccess;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.NavigableRole;

import org.jboss.logging.Logger;

/**
 * @author Steve Ebersole
 */
public abstract class AbstractDomainDataRegion extends AbstractRegion implements DomainDataRegion {
	private static final Logger log = Logger.getLogger( AbstractDomainDataRegion.class );

	private final SessionFactoryImplementor sessionFactory;
	private final CacheKeysFactory effectiveKeysFactory;

	private Map entityDataAccessMap;
	private Map naturalIdDataAccessMap;
	private Map collectionDataAccessMap;

	public AbstractDomainDataRegion(
			DomainDataRegionConfig regionConfig,
			RegionFactory regionFactory,
			CacheKeysFactory defaultKeysFactory,
			DomainDataRegionBuildingContext buildingContext) {
//		super( regionFactory.qualify( regionConfig.getRegionName() ), regionFactory );
		super( regionConfig.getRegionName(), regionFactory );

		this.sessionFactory = buildingContext.getSessionFactory();

		if ( defaultKeysFactory == null ) {
			defaultKeysFactory = DefaultCacheKeysFactory.INSTANCE;
		}
		this.effectiveKeysFactory = buildingContext.getEnforcedCacheKeysFactory() != null
				? buildingContext.getEnforcedCacheKeysFactory()
				: defaultKeysFactory;
	}

	/**
	 * Should be called at the end of the subtype's constructor, or at least after the
	 * `#super(...)` (aka, this type's constructor) call.  It's a timing issue - we need access
	 * to the DomainDataStorageAccess in DomainDataRegionTemplate but in methods initiated
	 * (atm) from AbstractDomainDataRegion's constructor
	 */
	protected void completeInstantiation(
			DomainDataRegionConfig regionConfig,
			DomainDataRegionBuildingContext buildingContext) {
		log.tracef( "DomainDataRegion created [%s]; key-factory = %s", regionConfig.getRegionName(), effectiveKeysFactory );

		this.entityDataAccessMap = generateEntityDataAccessMap( regionConfig );
		this.naturalIdDataAccessMap = generateNaturalIdDataAccessMap( regionConfig );
		this.collectionDataAccessMap = generateCollectionDataAccessMap( regionConfig );

	}

	public SessionFactoryImplementor getSessionFactory() {
		return sessionFactory;
	}

	public CacheKeysFactory getEffectiveKeysFactory() {
		return effectiveKeysFactory;
	}

	@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
	public NaturalIdDataAccess getNaturalIdDataAccess(NavigableRole rootEntityRole) {
		final NaturalIdDataAccess access = naturalIdDataAccessMap.get( rootEntityRole );
		if ( access == null ) {
			throw new IllegalArgumentException( "Caching was not configured for entity natural-id : " + rootEntityRole.getFullPath() );
		}
		return access;
	}

	@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;
	}

	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// creation

	protected abstract EntityDataAccess generateEntityAccess(EntityDataCachingConfig entityAccessConfig);
	protected abstract CollectionDataAccess generateCollectionAccess(CollectionDataCachingConfig cachingConfig);
	protected abstract NaturalIdDataAccess generateNaturalIdAccess(NaturalIdDataCachingConfig naturalIdAccessConfig);

	private Map generateEntityDataAccessMap(
			DomainDataRegionConfig regionConfig) {
		if ( regionConfig.getEntityCaching().isEmpty() ) {
			return Collections.emptyMap();
		}

		final Map accessMap = new ConcurrentHashMap<>();
		for ( EntityDataCachingConfig entityAccessConfig : regionConfig.getEntityCaching() ) {
			accessMap.computeIfAbsent(
					entityAccessConfig.getNavigableRole(),
					hierarchy -> generateEntityAccess( entityAccessConfig )
			);
		}

		return Collections.unmodifiableMap( accessMap );
	}

	private Map generateNaturalIdDataAccessMap(DomainDataRegionConfig regionConfig) {
		if ( regionConfig.getNaturalIdCaching().isEmpty() ) {
			return Collections.emptyMap();
		}

		final Map accessMap = new ConcurrentHashMap<>();
		for ( NaturalIdDataCachingConfig naturalIdAccessConfig : regionConfig.getNaturalIdCaching() ) {
			accessMap.computeIfAbsent(
					naturalIdAccessConfig.getNavigableRole(),
					hierarchy -> generateNaturalIdAccess( naturalIdAccessConfig )
			);
		}

		return Collections.unmodifiableMap( accessMap );
	}

	private Map generateCollectionDataAccessMap(
			DomainDataRegionConfig regionConfig) {
		if ( regionConfig.getCollectionCaching().isEmpty() ) {
			return Collections.emptyMap();
		}

		final Map accessMap = new ConcurrentHashMap<>();
		for ( CollectionDataCachingConfig cachingConfig : regionConfig.getCollectionCaching() ) {
			accessMap.computeIfAbsent(
					cachingConfig.getNavigableRole(),
					hierarchy -> generateCollectionAccess( cachingConfig )
			);
		}

		return Collections.unmodifiableMap( accessMap );
	}

	@Override
	public void clear() {
		for ( EntityDataAccess cacheAccess : entityDataAccessMap.values() ) {
			cacheAccess.evictAll();
		}

		for ( NaturalIdDataAccess cacheAccess : naturalIdDataAccessMap.values() ) {
			cacheAccess.evictAll();
		}

		for ( CollectionDataAccess cacheAccess : collectionDataAccessMap.values() ) {
			cacheAccess.evictAll();
		}
	}


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// destruction

	/**
	 * Optional interface caching implementors can implement in their
	 * CachedDomainDataAccess impls to automatically have them destroyed
	 * when this region is destroyed
	 */
	public interface Destructible {
		void destroy();
	}

	protected void releaseDataAccess(EntityDataAccess cacheAccess) {
		if ( Destructible.class.isInstance( cacheAccess ) ) {
			( (Destructible) cacheAccess ).destroy();
		}
	}

	protected void releaseDataAccess(NaturalIdDataAccess cacheAccess) {
		if ( Destructible.class.isInstance( cacheAccess ) ) {
			( (Destructible) cacheAccess ).destroy();
		}
	}

	protected void releaseDataAccess(CollectionDataAccess cacheAccess) {
		if ( Destructible.class.isInstance( cacheAccess ) ) {
			( (Destructible) cacheAccess ).destroy();
		}
	}

	@Override
	public void destroy() throws CacheException {
		for ( EntityDataAccess cacheAccess : entityDataAccessMap.values() ) {
			releaseDataAccess( cacheAccess );
		}

		for ( NaturalIdDataAccess cacheAccess : naturalIdDataAccessMap.values() ) {
			releaseDataAccess( cacheAccess );
		}

		for ( CollectionDataAccess cacheAccess : collectionDataAccessMap.values() ) {
			releaseDataAccess( cacheAccess );
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy