diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java index 31af96084b..3aa1b32e46 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java @@ -13,6 +13,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.boot.registry.selector.spi.StrategyCreator; import org.hibernate.boot.registry.selector.spi.StrategySelectionException; import org.hibernate.boot.registry.selector.spi.StrategySelector; @@ -26,8 +27,20 @@ import org.jboss.logging.Logger; public class StrategySelectorImpl implements StrategySelector { private static final Logger log = Logger.getLogger( StrategySelectorImpl.class ); - private final Map> namedStrategyImplementorByStrategyMap - = new ConcurrentHashMap>(); + + public static StrategyCreator STANDARD_STRATEGY_CREATOR = strategyClass -> { + try { + return strategyClass.newInstance(); + } + catch (Exception e) { + throw new StrategySelectionException( + String.format( "Could not instantiate named strategy class [%s]", strategyClass.getName() ), + e + ); + } + }; + + private final Map> namedStrategyImplementorByStrategyMap = new ConcurrentHashMap<>(); private final ClassLoaderService classLoaderService; @@ -44,7 +57,7 @@ public class StrategySelectorImpl implements StrategySelector { public void registerStrategyImplementor(Class strategy, String name, Class implementation) { Map namedStrategyImplementorMap = namedStrategyImplementorByStrategyMap.get( strategy ); if ( namedStrategyImplementorMap == null ) { - namedStrategyImplementorMap = new ConcurrentHashMap(); + namedStrategyImplementorMap = new ConcurrentHashMap<>(); namedStrategyImplementorByStrategyMap.put( strategy, namedStrategyImplementorMap ); } @@ -126,12 +139,7 @@ public class StrategySelectorImpl implements StrategySelector { return resolveDefaultableStrategy( strategy, strategyReference, - new Callable() { - @Override - public T call() { - return defaultValue; - } - } + (Callable) () -> defaultValue ); } @@ -141,6 +149,30 @@ public class StrategySelectorImpl implements StrategySelector { Class strategy, Object strategyReference, Callable defaultResolver) { + return (T) resolveStrategy( strategy, strategyReference, defaultResolver, STANDARD_STRATEGY_CREATOR ); + } + + @Override + public T resolveStrategy( + Class strategy, + Object strategyReference, + T defaultValue, + StrategyCreator creator) { + return resolveStrategy( + strategy, + strategyReference, + (Callable) () -> defaultValue, + creator + ); + } + + @SuppressWarnings("unchecked") + @Override + public T resolveStrategy( + Class strategy, + Object strategyReference, + Callable defaultResolver, + StrategyCreator creator) { if ( strategyReference == null ) { try { return defaultResolver.call(); @@ -163,7 +195,7 @@ public class StrategySelectorImpl implements StrategySelector { } try { - return implementationClass.newInstance(); + return creator.create( implementationClass ); } catch (Exception e) { throw new StrategySelectionException( diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategyCreator.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategyCreator.java new file mode 100644 index 0000000000..b561594491 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategyCreator.java @@ -0,0 +1,14 @@ +/* + * 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 . + */ +package org.hibernate.boot.registry.selector.spi; + +/** + * @author Steve Ebersole + */ +public interface StrategyCreator { + T create(Class strategyClass); +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java index e51ed8188f..8ac40c3cff 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java @@ -19,9 +19,9 @@ import org.hibernate.service.Service; * StrategySelector manages resolution of particular implementation by (possibly short) name via the * {@link #selectStrategyImplementor} method, which is the main contract here. As indicated in the docs of that * method the given name might be either a short registered name or the implementation FQN. As an example, consider - * resolving the {@link org.hibernate.engine.transaction.spi.TransactionFactory} implementation to use. To use the - * JDBC-based TransactionFactory the passed name might be either {@code "jdbc"} or - * {@code "org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory"} (which is the FQN). + * resolving the {@link org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder} implementation to use. To use the + * JDBC-based TransactionCoordinatorBuilder the passed name might be either {@code "jdbc"} or + * {@code "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl"} (which is the FQN). *

* Strategy implementations can be managed by {@link #registerStrategyImplementor} and * {@link #unRegisterStrategyImplementor}. Originally designed to help the OSGi use case, though no longer used there. @@ -135,4 +135,8 @@ public interface StrategySelector extends Service { * @return The strategy instance */ T resolveDefaultableStrategy(Class strategy, Object strategyReference, Callable defaultResolver); + + T resolveStrategy(Class strategy, Object strategyReference, Callable defaultResolver, StrategyCreator creator); + + T resolveStrategy(Class strategy, Object strategyReference, T defaultValue, StrategyCreator creator); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java index b0c23dd3cf..346c9b953a 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java @@ -20,6 +20,7 @@ import org.hibernate.SessionFactoryObserver; import org.hibernate.boot.SchemaAutoTooling; import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.cache.spi.QueryCacheFactory; import org.hibernate.cfg.BaselineSessionEventsListenerBuilder; import org.hibernate.context.spi.CurrentTenantIdentifierResolver; diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java index 644443b969..a01948ddd4 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java @@ -9,17 +9,16 @@ package org.hibernate.cache.internal; import java.util.Map; import java.util.Properties; -import org.hibernate.HibernateException; import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.spi.ServiceRegistryImplementor; -import org.jboss.logging.Logger; - /** * Initiator for the {@link RegionFactory} service. * @@ -27,9 +26,7 @@ import org.jboss.logging.Logger; * @author Brett Meyer */ public class RegionFactoryInitiator implements StandardServiceInitiator { - - private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, - RegionFactoryInitiator.class.getName() ); + private static final CoreMessageLogger LOG = CoreLogging.messageLogger( RegionFactoryInitiator.class ); /** * Singleton access @@ -63,26 +60,16 @@ public class RegionFactoryInitiator implements StandardServiceInitiator regionFactoryClass = registry.getService( StrategySelector.class ) - .selectStrategyImplementor( RegionFactory.class, setting ); - try { - regionFactory = regionFactoryClass.getConstructor( Properties.class ).newInstance( p ); - } - catch ( NoSuchMethodException e ) { - // no constructor accepting Properties found, try no arg constructor - LOG.debugf( - "%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.", - regionFactoryClass.getSimpleName() ); - regionFactory = regionFactoryClass.getConstructor().newInstance(); - } - } - catch ( Exception e ) { - throw new HibernateException( "could not instantiate RegionFactory [" + setting + "]", e ); - } + if ( useSecondLevelCache || useQueryCache ) { + final Object setting = configurationValues != null + ? configurationValues.get( AvailableSettings.CACHE_REGION_FACTORY ) + : null; + regionFactory = registry.getService( StrategySelector.class ).resolveStrategy( + RegionFactory.class, + setting, + NoCachingRegionFactory.INSTANCE, + new StrategyCreatorRegionFactoryImpl( p ) + ); } LOG.debugf( "Cache region factory : %s", regionFactory.getClass().getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/StrategyCreatorRegionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/StrategyCreatorRegionFactoryImpl.java new file mode 100644 index 0000000000..1f1c0df711 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/StrategyCreatorRegionFactoryImpl.java @@ -0,0 +1,68 @@ +/* + * 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 . + */ +package org.hibernate.cache.internal; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Properties; + +import org.hibernate.boot.registry.selector.spi.StrategyCreator; +import org.hibernate.cache.spi.RegionFactory; +import org.hibernate.service.spi.ServiceException; + +import org.jboss.logging.Logger; + +/** + * @author Steve Ebersole + */ +public class StrategyCreatorRegionFactoryImpl implements StrategyCreator { + private static final Logger log = Logger.getLogger( StrategyCreatorRegionFactoryImpl.class ); + + private final Properties properties; + + public StrategyCreatorRegionFactoryImpl(Properties properties) { + this.properties = properties; + } + + @Override + public RegionFactory create(Class strategyClass) { + assert RegionFactory.class.isAssignableFrom( strategyClass ); + + // first look for a constructor accepting Properties + try { + final Constructor ctor = strategyClass.getConstructor( Properties.class ); + return ctor.newInstance( properties ); + } + catch ( NoSuchMethodException e ) { + log.debugf( "RegionFactory impl [%s] did not provide constructor accepting Properties", strategyClass.getName() ); + } + catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { + throw new ServiceException( "Unable to call constructor of RegionFactory impl [" + strategyClass.getName() + "]", e ); + } + + // next try Map + try { + final Constructor ctor = strategyClass.getConstructor( Map.class ); + return ctor.newInstance( properties ); + } + catch ( NoSuchMethodException e ) { + log.debugf( "RegionFactory impl [%s] did not provide constructor accepting Properties", strategyClass.getName() ); + } + catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { + throw new ServiceException( "Unable to call constructor of RegionFactory impl [" + strategyClass.getName() + "]", e ); + } + + // finally try no-arg + try { + return strategyClass.newInstance(); + } + catch (IllegalAccessException | InstantiationException e) { + throw new ServiceException( "Unable to call constructor of RegionFactory impl [" + strategyClass.getName() + "]", e ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 09beda4f29..381d6102cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -686,14 +686,31 @@ public interface AvailableSettings { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** - * The {@link org.hibernate.cache.spi.RegionFactory} implementation class + * The {@link org.hibernate.cache.spi.RegionFactory} implementation. Can refer to:

    + *
  • an Object implementing {@link org.hibernate.cache.spi.RegionFactory}
  • + *
  • a Class implementing {@link org.hibernate.cache.spi.RegionFactory}
  • + *
  • FQN of a Class implementing {@link org.hibernate.cache.spi.RegionFactory}
  • + *
*/ String CACHE_REGION_FACTORY = "hibernate.cache.region.factory_class"; + /** + * Allow control to specify the {@link org.hibernate.cache.spi.CacheKeysFactory} impl to use. + * Can refer to:
    + *
  • an Object implementing {@link org.hibernate.cache.spi.CacheKeysFactory}
  • + *
  • a Class implementing {@link org.hibernate.cache.spi.CacheKeysFactory}
  • + *
  • FQN of a Class implementing {@link org.hibernate.cache.spi.CacheKeysFactory}
  • + *
+ * + * @since 5.2 - note that currently this is only honored for hibernate-infinispan + */ + String CACHE_KEYS_FACTORY = "hibernate.cache.keys_factory"; + /** * The CacheProvider implementation class */ String CACHE_PROVIDER_CONFIG = "hibernate.cache.provider_configuration_file_resource_path"; + /** * Enable the second-level cache (enabled by default) */ diff --git a/hibernate-core/src/test/java/org/hibernate/test/cache/SharedRegionTest.java b/hibernate-core/src/test/java/org/hibernate/test/cache/SharedRegionTest.java new file mode 100644 index 0000000000..95611c2815 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cache/SharedRegionTest.java @@ -0,0 +1,94 @@ +/* + * 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 . + */ +package org.hibernate.test.cache; + +import java.util.Properties; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.Session; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.internal.SimpleCacheKeysFactory; +import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cfg.AvailableSettings; + +import org.hibernate.testing.cache.CachingRegionFactory; +import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertNull; + +/** + * @author Steve Ebersole + */ +public class SharedRegionTest extends BaseNonConfigCoreFunctionalTestCase { + @Override + protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { + super.configureStandardServiceRegistryBuilder( ssrb ); + ssrb.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, true ); + ssrb.applySetting( AvailableSettings.CACHE_REGION_FACTORY, new CachingRegionFactory() ); + } + + @Override + protected void applyMetadataSources(MetadataSources metadataSources) { + super.applyMetadataSources( metadataSources ); + metadataSources.addAnnotatedClass( StateCodes.class ); + metadataSources.addAnnotatedClass( ZipCodes.class ); + } + + @Test + public void test() { + // create a StateCodes + Session s = openSession(); + s.beginTransaction(); + s.save( new StateCodes( 1 ) ); + s.getTransaction().commit(); + s.close(); + + // now try to load a ZipCodes using the same id : should just return null rather than blow up :) + s = openSession(); + s.beginTransaction(); + ZipCodes zc = s.find( ZipCodes.class, 1 ); + assertNull( zc ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + s.find( ZipCodes.class, 1 ); + s.getTransaction().commit(); + s.close(); + } + + @Entity( name="StateCodes" ) + @Cache( region="com.acme.referenceData", usage = CacheConcurrencyStrategy.READ_WRITE ) + public static class StateCodes { + @Id + public Integer id; + + public StateCodes() { + } + + public StateCodes(Integer id) { + this.id = id; + } + } + + @Entity( name = "ZipCodes" ) + @Cache( region="com.acme.referenceData", usage = CacheConcurrencyStrategy.READ_WRITE ) + public static class ZipCodes { + @Id + public Integer id; + } +} diff --git a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java index 538bd86c56..0a777d473e 100644 --- a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java +++ b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java @@ -18,6 +18,7 @@ import java.util.function.Consumer; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.MultiTenancyStrategy; +import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.cache.CacheException; import org.hibernate.cache.infinispan.collection.CollectionRegionImpl; @@ -42,6 +43,7 @@ import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.TimestampsRegion; import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.ServiceRegistry; @@ -273,6 +275,7 @@ public class InfinispanRegionFactory implements RegionFactory { */ protected final Map configOverrides = new HashMap<>(); + private CacheKeysFactory cacheKeysFactory; private ConfigurationBuilderHolder defaultConfiguration; private final Map dataTypeConfigurations = new HashMap<>(); private EmbeddedCacheManager manager; @@ -301,22 +304,27 @@ public class InfinispanRegionFactory implements RegionFactory { } @Override - public CollectionRegion buildCollectionRegion( - String regionName, - Properties properties, - CacheDataDescription metadata) throws CacheException { + public CollectionRegion buildCollectionRegion(String regionName, Map configValues, CacheDataDescription metadata) { if ( log.isDebugEnabled() ) { log.debug( "Building collection cache region [" + regionName + "]" ); } final AdvancedCache cache = getCache( regionName, DataType.COLLECTION, metadata); - final CollectionRegionImpl region = new CollectionRegionImpl( cache, regionName, transactionManager, metadata, this, buildCacheKeysFactory() ); + final CollectionRegionImpl region = new CollectionRegionImpl( cache, regionName, transactionManager, metadata, this, getCacheKeysFactory() ); startRegion( region ); return region; } @Override - public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) - throws CacheException { + @SuppressWarnings("unchecked") + public CollectionRegion buildCollectionRegion( + String regionName, + Properties properties, + CacheDataDescription metadata) throws CacheException { + return buildCollectionRegion( regionName, (Map) properties, metadata ); + } + + @Override + public EntityRegion buildEntityRegion(String regionName, Map configValues, CacheDataDescription metadata) { if ( log.isDebugEnabled() ) { log.debugf( "Building entity cache region [%s] (mutable=%s, versioned=%s)", @@ -326,26 +334,36 @@ public class InfinispanRegionFactory implements RegionFactory { ); } final AdvancedCache cache = getCache( regionName, metadata.isMutable() ? DataType.ENTITY : DataType.IMMUTABLE_ENTITY, metadata ); - final EntityRegionImpl region = new EntityRegionImpl( cache, regionName, transactionManager, metadata, this, buildCacheKeysFactory() ); + final EntityRegionImpl region = new EntityRegionImpl( cache, regionName, transactionManager, metadata, this, getCacheKeysFactory() ); startRegion( region ); return region; } @Override - public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) - throws CacheException { + @SuppressWarnings("unchecked") + public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) { + return buildEntityRegion( regionName, (Map) properties, metadata ); + } + + @Override + public NaturalIdRegion buildNaturalIdRegion(String regionName, Map configValues, CacheDataDescription metadata) { if ( log.isDebugEnabled() ) { log.debug("Building natural id cache region [" + regionName + "]"); } final AdvancedCache cache = getCache( regionName, DataType.NATURAL_ID, metadata); - final NaturalIdRegionImpl region = new NaturalIdRegionImpl( cache, regionName, transactionManager, metadata, this, buildCacheKeysFactory()); + final NaturalIdRegionImpl region = new NaturalIdRegionImpl( cache, regionName, transactionManager, metadata, this, getCacheKeysFactory()); startRegion( region ); return region; } @Override - public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) - throws CacheException { + @SuppressWarnings("unchecked") + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) { + return buildNaturalIdRegion( regionName, (Map) properties, metadata ); + } + + @Override + public QueryResultsRegion buildQueryResultsRegion(String regionName, Map configValues) { if ( log.isDebugEnabled() ) { log.debug( "Building query results cache region [" + regionName + "]" ); } @@ -357,8 +375,13 @@ public class InfinispanRegionFactory implements RegionFactory { } @Override - public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) - throws CacheException { + @SuppressWarnings("unchecked") + public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) { + return buildQueryResultsRegion( regionName, (Map) properties ); + } + + @Override + public TimestampsRegion buildTimestampsRegion(String regionName, Map configValues) { if ( log.isDebugEnabled() ) { log.debug( "Building timestamps cache region [" + regionName + "]" ); } @@ -368,6 +391,12 @@ public class InfinispanRegionFactory implements RegionFactory { return region; } + @Override + @SuppressWarnings("unchecked") + public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) { + return buildTimestampsRegion( regionName, (Map) properties ); + } + protected TimestampsRegionImpl createTimestampsRegion( AdvancedCache cache, String regionName) { if ( Caches.isClustered(cache) ) { @@ -382,13 +411,8 @@ public class InfinispanRegionFactory implements RegionFactory { return dataTypeConfigurations.get(DataType.PENDING_PUTS); } - private CacheKeysFactory buildCacheKeysFactory() { - if (settings.getMultiTenancyStrategy() != MultiTenancyStrategy.NONE) { - return DefaultCacheKeysFactory.INSTANCE; - } - else { - return SimpleCacheKeysFactory.INSTANCE; - } + private CacheKeysFactory getCacheKeysFactory() { + return cacheKeysFactory; } @Override @@ -418,6 +442,10 @@ public class InfinispanRegionFactory implements RegionFactory { @Override public void start(SessionFactoryOptions settings, Properties properties) throws CacheException { log.debug( "Starting Infinispan region factory" ); + + // determine the CacheKeysFactory to use... + this.cacheKeysFactory = determineCacheKeysFactory( settings, properties ); + try { this.settings = settings; transactionManagerlookup = createTransactionManagerLookup( settings, properties ); @@ -449,6 +477,18 @@ public class InfinispanRegionFactory implements RegionFactory { } } + private CacheKeysFactory determineCacheKeysFactory(SessionFactoryOptions settings, Properties properties) { + final CacheKeysFactory implicitFactory = settings.getMultiTenancyStrategy() != MultiTenancyStrategy.NONE + ? DefaultCacheKeysFactory.INSTANCE + : SimpleCacheKeysFactory.INSTANCE; + + return settings.getServiceRegistry().getService( StrategySelector.class ).resolveDefaultableStrategy( + CacheKeysFactory.class, + properties.get( AvailableSettings.CACHE_KEYS_FACTORY ), + implicitFactory + ); + } + /* This method is overridden in WildFly, so the signature must not change. */ /* In WF, the global configuration setting is ignored */ protected EmbeddedCacheManager createCacheManager(Properties properties, ServiceRegistry serviceRegistry) { diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseCollectionRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseCollectionRegionAccessStrategy.java index 973b7dd501..2fc05ea3a5 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseCollectionRegionAccessStrategy.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseCollectionRegionAccessStrategy.java @@ -6,7 +6,6 @@ */ package org.hibernate.testing.cache; -import org.hibernate.cache.internal.DefaultCacheKeysFactory; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -40,12 +39,12 @@ class BaseCollectionRegionAccessStrategy extends BaseRegionAccessStrategy implem @Override public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.createCollectionKey( id, persister, factory, tenantIdentifier ); + return region.getRegionFactory().getCacheKeysFactory().createCollectionKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.getCollectionId(cacheKey); + return region.getRegionFactory().getCacheKeysFactory().getCollectionId( cacheKey ); } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseEntityRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseEntityRegionAccessStrategy.java index e46ddfbfe5..cfd9ea59be 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseEntityRegionAccessStrategy.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseEntityRegionAccessStrategy.java @@ -7,7 +7,6 @@ package org.hibernate.testing.cache; import org.hibernate.cache.CacheException; -import org.hibernate.cache.internal.DefaultCacheKeysFactory; import org.hibernate.cache.spi.EntityRegion; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; import org.hibernate.cache.spi.access.SoftLock; @@ -65,11 +64,11 @@ class BaseEntityRegionAccessStrategy extends BaseRegionAccessStrategy implements @Override public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.createEntityKey( id, persister, factory, tenantIdentifier ); + return region.getRegionFactory().getCacheKeysFactory().createEntityKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.getEntityId(cacheKey); + return region.getRegionFactory().getCacheKeysFactory().getEntityId( cacheKey ); } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseGeneralDataRegion.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseGeneralDataRegion.java index 32cc452627..0f01d791d8 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseGeneralDataRegion.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseGeneralDataRegion.java @@ -18,8 +18,8 @@ import org.jboss.logging.Logger; class BaseGeneralDataRegion extends BaseRegion implements GeneralDataRegion { private static final Logger LOG = Logger.getLogger( BaseGeneralDataRegion.class.getName() ); - BaseGeneralDataRegion(String name) { - super( name ); + BaseGeneralDataRegion(CachingRegionFactory cachingRegionFactory, String name) { + super( cachingRegionFactory, name ); } @Override diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseNaturalIdRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseNaturalIdRegionAccessStrategy.java index 3605158830..513cd0dd7e 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseNaturalIdRegionAccessStrategy.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseNaturalIdRegionAccessStrategy.java @@ -7,7 +7,6 @@ package org.hibernate.testing.cache; import org.hibernate.cache.CacheException; -import org.hibernate.cache.internal.DefaultCacheKeysFactory; import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; import org.hibernate.cache.spi.access.SoftLock; @@ -61,11 +60,11 @@ class BaseNaturalIdRegionAccessStrategy extends BaseRegionAccessStrategy impleme @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) { - return DefaultCacheKeysFactory.createNaturalIdKey( naturalIdValues, persister, session ); + return region.getRegionFactory().getCacheKeysFactory().createNaturalIdKey( naturalIdValues, persister, session ); } @Override public Object[] getNaturalIdValues(Object cacheKey) { - return DefaultCacheKeysFactory.getNaturalIdValues( cacheKey ); + return region.getRegionFactory().getCacheKeysFactory().getNaturalIdValues( cacheKey ); } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseRegion.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseRegion.java index 9dd38df1b5..7b7cf3f527 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseRegion.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseRegion.java @@ -17,17 +17,19 @@ import org.hibernate.cache.spi.Region; * @author Strong Liu */ public class BaseRegion implements Region { - protected final Map cache = new ConcurrentHashMap(); + private final CachingRegionFactory cachingRegionFactory; private final String name; + protected final Map cache = new ConcurrentHashMap(); + private static int timeout = Timestamper.ONE_MS * 60000; //60s - BaseRegion(String name) { + BaseRegion(CachingRegionFactory cachingRegionFactory, String name) { + this.cachingRegionFactory = cachingRegionFactory; this.name = name; } - @Override - public boolean contains(Object key) { - return key != null ? cache.containsKey( key ) : false; + public CachingRegionFactory getRegionFactory() { + return cachingRegionFactory; } @Override @@ -35,6 +37,11 @@ public class BaseRegion implements Region { return name; } + @Override + public boolean contains(Object key) { + return key != null ? cache.containsKey( key ) : false; + } + @Override public void destroy() throws CacheException { cache.clear(); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseTransactionalDataRegion.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseTransactionalDataRegion.java index e33f650e94..4a84bdfa84 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseTransactionalDataRegion.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseTransactionalDataRegion.java @@ -15,8 +15,8 @@ import org.hibernate.cache.spi.TransactionalDataRegion; class BaseTransactionalDataRegion extends BaseGeneralDataRegion implements TransactionalDataRegion { private final CacheDataDescription metadata; - BaseTransactionalDataRegion(String name, CacheDataDescription metadata) { - super( name ); + BaseTransactionalDataRegion(CachingRegionFactory cachingRegionFactory, String name, CacheDataDescription metadata) { + super( cachingRegionFactory, name ); this.metadata = metadata; } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/CachingRegionFactory.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/CachingRegionFactory.java index ce12c23831..fbd9bbb70f 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/CachingRegionFactory.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/CachingRegionFactory.java @@ -10,7 +10,9 @@ import java.util.Properties; import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; import org.hibernate.cache.spi.NaturalIdRegion; @@ -28,19 +30,34 @@ public class CachingRegionFactory implements RegionFactory { private static final Logger LOG = Logger.getLogger( CachingRegionFactory.class.getName() ); public static String DEFAULT_ACCESSTYPE = "DefaultAccessType"; + + private final CacheKeysFactory cacheKeysFactory; + private SessionFactoryOptions settings; private Properties properties; public CachingRegionFactory() { - LOG.warn( "CachingRegionFactory should be only used for testing." ); + this( DefaultCacheKeysFactory.INSTANCE, null ); + } + + public CachingRegionFactory(CacheKeysFactory cacheKeysFactory) { + this( cacheKeysFactory, null ); } public CachingRegionFactory(Properties properties) { - //add here to avoid run into catch + this( DefaultCacheKeysFactory.INSTANCE, properties ); + } + + public CachingRegionFactory(CacheKeysFactory cacheKeysFactory, Properties properties) { LOG.warn( "CachingRegionFactory should be only used for testing." ); + this.cacheKeysFactory = cacheKeysFactory; this.properties = properties; } + public CacheKeysFactory getCacheKeysFactory() { + return cacheKeysFactory; + } + @Override public void start(SessionFactoryOptions settings, Properties properties) throws CacheException { this.settings = settings; @@ -72,43 +89,42 @@ public class CachingRegionFactory implements RegionFactory { @Override public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { - return new EntityRegionImpl( regionName, metadata, settings ); + return new EntityRegionImpl( this, regionName, metadata, settings ); } @Override public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { - return new NaturalIdRegionImpl( regionName, metadata, settings ); + return new NaturalIdRegionImpl( this, regionName, metadata, settings ); } @Override public CollectionRegion buildCollectionRegion( String regionName, Properties properties, - CacheDataDescription metadata) - throws CacheException { - return new CollectionRegionImpl( regionName, metadata, settings ); + CacheDataDescription metadata) throws CacheException { + return new CollectionRegionImpl( this, regionName, metadata, settings ); } @Override public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException { - return new QueryResultsRegionImpl( regionName ); + return new QueryResultsRegionImpl( this, regionName ); } @Override public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException { - return new TimestampsRegionImpl( regionName ); + return new TimestampsRegionImpl( this, regionName ); } private static class QueryResultsRegionImpl extends BaseGeneralDataRegion implements QueryResultsRegion { - QueryResultsRegionImpl(String name) { - super( name ); + QueryResultsRegionImpl(CachingRegionFactory cachingRegionFactory, String name) { + super( cachingRegionFactory, name ); } } private static class TimestampsRegionImpl extends BaseGeneralDataRegion implements TimestampsRegion { - TimestampsRegionImpl(String name) { - super( name ); + TimestampsRegionImpl(CachingRegionFactory cachingRegionFactory, String name) { + super( cachingRegionFactory, name ); } } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/CollectionRegionImpl.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/CollectionRegionImpl.java index cc6dacf32b..8d087d2266 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/CollectionRegionImpl.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/CollectionRegionImpl.java @@ -23,8 +23,12 @@ class CollectionRegionImpl extends BaseTransactionalDataRegion implements Collec private final SessionFactoryOptions settings; - CollectionRegionImpl(String name, CacheDataDescription metadata, SessionFactoryOptions settings) { - super( name, metadata ); + CollectionRegionImpl( + CachingRegionFactory cachingRegionFactory, + String name, + CacheDataDescription metadata, + SessionFactoryOptions settings) { + super( cachingRegionFactory, name, metadata ); this.settings = settings; } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/EntityRegionImpl.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/EntityRegionImpl.java index bd32943b88..360b13278a 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/EntityRegionImpl.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/EntityRegionImpl.java @@ -18,14 +18,17 @@ import org.jboss.logging.Logger; /** * @author Strong Liu */ -class EntityRegionImpl extends BaseTransactionalDataRegion implements EntityRegion { +public class EntityRegionImpl extends BaseTransactionalDataRegion implements EntityRegion { private static final Logger LOG = Logger.getLogger( EntityRegionImpl.class ); - private final SessionFactoryOptions settings; - EntityRegionImpl(String name, CacheDataDescription metadata, SessionFactoryOptions settings) { - super( name, metadata ); + protected EntityRegionImpl( + CachingRegionFactory cachingRegionFactory, + String name, + CacheDataDescription metadata, + SessionFactoryOptions settings) { + super( cachingRegionFactory, name, metadata ); this.settings = settings; } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/NaturalIdRegionImpl.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/NaturalIdRegionImpl.java index 034426ff05..7317b145d3 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/NaturalIdRegionImpl.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/NaturalIdRegionImpl.java @@ -23,8 +23,12 @@ class NaturalIdRegionImpl extends BaseTransactionalDataRegion implements Natural private final SessionFactoryOptions settings; - NaturalIdRegionImpl(String name, CacheDataDescription metadata, SessionFactoryOptions settings) { - super( name, metadata ); + NaturalIdRegionImpl( + CachingRegionFactory cachingRegionFactory, + String name, + CacheDataDescription metadata, + SessionFactoryOptions settings) { + super( cachingRegionFactory, name, metadata ); this.settings = settings; } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteCollectionRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteCollectionRegionAccessStrategy.java index 5f1338d0a4..833b040720 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteCollectionRegionAccessStrategy.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteCollectionRegionAccessStrategy.java @@ -48,11 +48,11 @@ class ReadWriteCollectionRegionAccessStrategy extends AbstractReadWriteAccessStr @Override public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.createCollectionKey( id, persister, factory, tenantIdentifier ); + return region.getRegionFactory().getCacheKeysFactory().createCollectionKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.getCollectionId( cacheKey ); + return region.getRegionFactory().getCacheKeysFactory().getCollectionId( cacheKey ); } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteEntityRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteEntityRegionAccessStrategy.java index 037f8c8c03..4ca4dd6fcd 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteEntityRegionAccessStrategy.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteEntityRegionAccessStrategy.java @@ -110,11 +110,11 @@ class ReadWriteEntityRegionAccessStrategy extends AbstractReadWriteAccessStrateg @Override public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.createEntityKey( id, persister, factory, tenantIdentifier ); + return region.getRegionFactory().getCacheKeysFactory().createEntityKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.getEntityId( cacheKey ); + return region.getRegionFactory().getCacheKeysFactory().getEntityId( cacheKey ); } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteNaturalIdRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteNaturalIdRegionAccessStrategy.java index f00310a301..0a519795d4 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteNaturalIdRegionAccessStrategy.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteNaturalIdRegionAccessStrategy.java @@ -9,7 +9,6 @@ package org.hibernate.testing.cache; import java.util.Comparator; import org.hibernate.cache.CacheException; -import org.hibernate.cache.internal.DefaultCacheKeysFactory; import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; import org.hibernate.cache.spi.access.SoftLock; @@ -107,11 +106,11 @@ class ReadWriteNaturalIdRegionAccessStrategy extends AbstractReadWriteAccessStra @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) { - return DefaultCacheKeysFactory.createNaturalIdKey( naturalIdValues, persister, session ); + return region.getRegionFactory().getCacheKeysFactory().createNaturalIdKey( naturalIdValues, persister, session ); } @Override public Object[] getNaturalIdValues(Object cacheKey) { - return DefaultCacheKeysFactory.getNaturalIdValues( cacheKey ); + return region.getRegionFactory().getCacheKeysFactory().getNaturalIdValues( cacheKey ); } }