Skip to content

Commit 3a0824a

Browse files
committed
HHH-10287 - Cache keys no longer include the entity type
1 parent 114ea15 commit 3a0824a

22 files changed

+395
-108
lines changed

hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
1515
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
16+
import org.hibernate.boot.registry.selector.spi.StrategyCreator;
1617
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
1718
import org.hibernate.boot.registry.selector.spi.StrategySelector;
1819

@@ -26,8 +27,20 @@
2627
public class StrategySelectorImpl implements StrategySelector {
2728
private static final Logger log = Logger.getLogger( StrategySelectorImpl.class );
2829

29-
private final Map<Class,Map<String,Class>> namedStrategyImplementorByStrategyMap
30-
= new ConcurrentHashMap<Class, Map<String, Class>>();
30+
31+
public static StrategyCreator STANDARD_STRATEGY_CREATOR = strategyClass -> {
32+
try {
33+
return strategyClass.newInstance();
34+
}
35+
catch (Exception e) {
36+
throw new StrategySelectionException(
37+
String.format( "Could not instantiate named strategy class [%s]", strategyClass.getName() ),
38+
e
39+
);
40+
}
41+
};
42+
43+
private final Map<Class,Map<String,Class>> namedStrategyImplementorByStrategyMap = new ConcurrentHashMap<>();
3144

3245
private final ClassLoaderService classLoaderService;
3346

@@ -44,7 +57,7 @@ public StrategySelectorImpl(ClassLoaderService classLoaderService) {
4457
public <T> void registerStrategyImplementor(Class<T> strategy, String name, Class<? extends T> implementation) {
4558
Map<String,Class> namedStrategyImplementorMap = namedStrategyImplementorByStrategyMap.get( strategy );
4659
if ( namedStrategyImplementorMap == null ) {
47-
namedStrategyImplementorMap = new ConcurrentHashMap<String, Class>();
60+
namedStrategyImplementorMap = new ConcurrentHashMap<>();
4861
namedStrategyImplementorByStrategyMap.put( strategy, namedStrategyImplementorMap );
4962
}
5063

@@ -126,12 +139,7 @@ public <T> T resolveDefaultableStrategy(Class<T> strategy, Object strategyRefere
126139
return resolveDefaultableStrategy(
127140
strategy,
128141
strategyReference,
129-
new Callable<T>() {
130-
@Override
131-
public T call() {
132-
return defaultValue;
133-
}
134-
}
142+
(Callable<T>) () -> defaultValue
135143
);
136144
}
137145

@@ -141,6 +149,30 @@ public <T> T resolveDefaultableStrategy(
141149
Class<T> strategy,
142150
Object strategyReference,
143151
Callable<T> defaultResolver) {
152+
return (T) resolveStrategy( strategy, strategyReference, defaultResolver, STANDARD_STRATEGY_CREATOR );
153+
}
154+
155+
@Override
156+
public <T> T resolveStrategy(
157+
Class<T> strategy,
158+
Object strategyReference,
159+
T defaultValue,
160+
StrategyCreator<T> creator) {
161+
return resolveStrategy(
162+
strategy,
163+
strategyReference,
164+
(Callable<T>) () -> defaultValue,
165+
creator
166+
);
167+
}
168+
169+
@SuppressWarnings("unchecked")
170+
@Override
171+
public <T> T resolveStrategy(
172+
Class<T> strategy,
173+
Object strategyReference,
174+
Callable<T> defaultResolver,
175+
StrategyCreator<T> creator) {
144176
if ( strategyReference == null ) {
145177
try {
146178
return defaultResolver.call();
@@ -163,7 +195,7 @@ public <T> T resolveDefaultableStrategy(
163195
}
164196

165197
try {
166-
return implementationClass.newInstance();
198+
return creator.create( implementationClass );
167199
}
168200
catch (Exception e) {
169201
throw new StrategySelectionException(
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.boot.registry.selector.spi;
8+
9+
/**
10+
* @author Steve Ebersole
11+
*/
12+
public interface StrategyCreator<T> {
13+
T create(Class<? extends T> strategyClass);
14+
}

hibernate-core/src/main/java/org/hibernate/boot/registry/selector/spi/StrategySelector.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
* StrategySelector manages resolution of particular implementation by (possibly short) name via the
2020
* {@link #selectStrategyImplementor} method, which is the main contract here. As indicated in the docs of that
2121
* method the given name might be either a short registered name or the implementation FQN. As an example, consider
22-
* resolving the {@link org.hibernate.engine.transaction.spi.TransactionFactory} implementation to use. To use the
23-
* JDBC-based TransactionFactory the passed name might be either {@code "jdbc"} or
24-
* {@code "org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory"} (which is the FQN).
22+
* resolving the {@link org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder} implementation to use. To use the
23+
* JDBC-based TransactionCoordinatorBuilder the passed name might be either {@code "jdbc"} or
24+
* {@code "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl"} (which is the FQN).
2525
* <p/>
2626
* Strategy implementations can be managed by {@link #registerStrategyImplementor} and
2727
* {@link #unRegisterStrategyImplementor}. Originally designed to help the OSGi use case, though no longer used there.
@@ -135,4 +135,8 @@ public interface StrategySelector extends Service {
135135
* @return The strategy instance
136136
*/
137137
<T> T resolveDefaultableStrategy(Class<T> strategy, Object strategyReference, Callable<T> defaultResolver);
138+
139+
<T> T resolveStrategy(Class<T> strategy, Object strategyReference, Callable<T> defaultResolver, StrategyCreator<T> creator);
140+
141+
<T> T resolveStrategy(Class<T> strategy, Object strategyReference, T defaultValue, StrategyCreator<T> creator);
138142
}

hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.hibernate.boot.SchemaAutoTooling;
2020
import org.hibernate.boot.TempTableDdlTransactionHandling;
2121
import org.hibernate.boot.registry.StandardServiceRegistry;
22+
import org.hibernate.cache.spi.CacheKeysFactory;
2223
import org.hibernate.cache.spi.QueryCacheFactory;
2324
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
2425
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;

hibernate-core/src/main/java/org/hibernate/cache/internal/RegionFactoryInitiator.java

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,24 @@
99
import java.util.Map;
1010
import java.util.Properties;
1111

12-
import org.hibernate.HibernateException;
1312
import org.hibernate.boot.registry.StandardServiceInitiator;
13+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
1414
import org.hibernate.boot.registry.selector.spi.StrategySelector;
1515
import org.hibernate.cache.spi.RegionFactory;
1616
import org.hibernate.cfg.AvailableSettings;
17+
import org.hibernate.internal.CoreLogging;
1718
import org.hibernate.internal.CoreMessageLogger;
1819
import org.hibernate.internal.util.config.ConfigurationHelper;
1920
import org.hibernate.service.spi.ServiceRegistryImplementor;
2021

21-
import org.jboss.logging.Logger;
22-
2322
/**
2423
* Initiator for the {@link RegionFactory} service.
2524
*
2625
* @author Hardy Ferentschik
2726
* @author Brett Meyer
2827
*/
2928
public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFactory> {
30-
31-
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
32-
RegionFactoryInitiator.class.getName() );
29+
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( RegionFactoryInitiator.class );
3330

3431
/**
3532
* Singleton access
@@ -63,26 +60,16 @@ public RegionFactory initiateService(Map configurationValues, ServiceRegistryImp
6360

6461
// The cache provider is needed when we either have second-level cache enabled
6562
// or query cache enabled. Note that useSecondLevelCache is enabled by default
66-
final String setting = ConfigurationHelper.getString( AvailableSettings.CACHE_REGION_FACTORY,
67-
configurationValues, null );
68-
if ( ( useSecondLevelCache || useQueryCache ) && setting != null ) {
69-
try {
70-
final Class<? extends RegionFactory> regionFactoryClass = registry.getService( StrategySelector.class )
71-
.selectStrategyImplementor( RegionFactory.class, setting );
72-
try {
73-
regionFactory = regionFactoryClass.getConstructor( Properties.class ).newInstance( p );
74-
}
75-
catch ( NoSuchMethodException e ) {
76-
// no constructor accepting Properties found, try no arg constructor
77-
LOG.debugf(
78-
"%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.",
79-
regionFactoryClass.getSimpleName() );
80-
regionFactory = regionFactoryClass.getConstructor().newInstance();
81-
}
82-
}
83-
catch ( Exception e ) {
84-
throw new HibernateException( "could not instantiate RegionFactory [" + setting + "]", e );
85-
}
63+
if ( useSecondLevelCache || useQueryCache ) {
64+
final Object setting = configurationValues != null
65+
? configurationValues.get( AvailableSettings.CACHE_REGION_FACTORY )
66+
: null;
67+
regionFactory = registry.getService( StrategySelector.class ).resolveStrategy(
68+
RegionFactory.class,
69+
setting,
70+
NoCachingRegionFactory.INSTANCE,
71+
new StrategyCreatorRegionFactoryImpl( p )
72+
);
8673
}
8774

8875
LOG.debugf( "Cache region factory : %s", regionFactory.getClass().getName() );
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.cache.internal;
8+
9+
import java.lang.reflect.Constructor;
10+
import java.lang.reflect.InvocationTargetException;
11+
import java.util.Map;
12+
import java.util.Properties;
13+
14+
import org.hibernate.boot.registry.selector.spi.StrategyCreator;
15+
import org.hibernate.cache.spi.RegionFactory;
16+
import org.hibernate.service.spi.ServiceException;
17+
18+
import org.jboss.logging.Logger;
19+
20+
/**
21+
* @author Steve Ebersole
22+
*/
23+
public class StrategyCreatorRegionFactoryImpl implements StrategyCreator<RegionFactory> {
24+
private static final Logger log = Logger.getLogger( StrategyCreatorRegionFactoryImpl.class );
25+
26+
private final Properties properties;
27+
28+
public StrategyCreatorRegionFactoryImpl(Properties properties) {
29+
this.properties = properties;
30+
}
31+
32+
@Override
33+
public RegionFactory create(Class<? extends RegionFactory> strategyClass) {
34+
assert RegionFactory.class.isAssignableFrom( strategyClass );
35+
36+
// first look for a constructor accepting Properties
37+
try {
38+
final Constructor<? extends RegionFactory> ctor = strategyClass.getConstructor( Properties.class );
39+
return ctor.newInstance( properties );
40+
}
41+
catch ( NoSuchMethodException e ) {
42+
log.debugf( "RegionFactory impl [%s] did not provide constructor accepting Properties", strategyClass.getName() );
43+
}
44+
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
45+
throw new ServiceException( "Unable to call constructor of RegionFactory impl [" + strategyClass.getName() + "]", e );
46+
}
47+
48+
// next try Map
49+
try {
50+
final Constructor<? extends RegionFactory> ctor = strategyClass.getConstructor( Map.class );
51+
return ctor.newInstance( properties );
52+
}
53+
catch ( NoSuchMethodException e ) {
54+
log.debugf( "RegionFactory impl [%s] did not provide constructor accepting Properties", strategyClass.getName() );
55+
}
56+
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
57+
throw new ServiceException( "Unable to call constructor of RegionFactory impl [" + strategyClass.getName() + "]", e );
58+
}
59+
60+
// finally try no-arg
61+
try {
62+
return strategyClass.newInstance();
63+
}
64+
catch (IllegalAccessException | InstantiationException e) {
65+
throw new ServiceException( "Unable to call constructor of RegionFactory impl [" + strategyClass.getName() + "]", e );
66+
}
67+
}
68+
}

hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,14 +891,31 @@ public interface AvailableSettings {
891891
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
892892

893893
/**
894-
* The {@link org.hibernate.cache.spi.RegionFactory} implementation class
894+
* The {@link org.hibernate.cache.spi.RegionFactory} implementation. Can refer to:<ul>
895+
* <li>an Object implementing {@link org.hibernate.cache.spi.RegionFactory}</li>
896+
* <li>a Class implementing {@link org.hibernate.cache.spi.RegionFactory}</li>
897+
* <li>FQN of a Class implementing {@link org.hibernate.cache.spi.RegionFactory}</li>
898+
* </ul>
895899
*/
896900
String CACHE_REGION_FACTORY = "hibernate.cache.region.factory_class";
897901

902+
/**
903+
* Allow control to specify the {@link org.hibernate.cache.spi.CacheKeysFactory} impl to use.
904+
* Can refer to:<ul>
905+
* <li>an Object implementing {@link org.hibernate.cache.spi.CacheKeysFactory}</li>
906+
* <li>a Class implementing {@link org.hibernate.cache.spi.CacheKeysFactory}</li>
907+
* <li>FQN of a Class implementing {@link org.hibernate.cache.spi.CacheKeysFactory}</li>
908+
* </ul>
909+
*
910+
* @since 5.2 - note that currently this is only honored for hibernate-infinispan
911+
*/
912+
String CACHE_KEYS_FACTORY = "hibernate.cache.keys_factory";
913+
898914
/**
899915
* The <tt>CacheProvider</tt> implementation class
900916
*/
901917
String CACHE_PROVIDER_CONFIG = "hibernate.cache.provider_configuration_file_resource_path";
918+
902919
/**
903920
* Enable the second-level cache (enabled by default)
904921
*/
@@ -1474,5 +1491,4 @@ public interface AvailableSettings {
14741491
* The default behavior is to allow access unless the session is bootstrapped via JPA.
14751492
*/
14761493
String ALLOW_JTA_TRANSACTION_ACCESS = "hibernate.jta.allowTransactionAccess";
1477-
14781494
}

0 commit comments

Comments
 (0)