HHH-13586 : ClassCastException when using a single region name for both entity and query results
(cherry picked from commit 2076c68ddf
)
This commit is contained in:
parent
1f48df3ee5
commit
6c4643f265
|
@ -48,6 +48,7 @@ import org.hibernate.pretty.MessageHelper;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Strong Liu
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildingContext {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( EnabledCaching.class );
|
||||
|
@ -57,6 +58,10 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin
|
|||
|
||||
private final Map<String,Region> regionsByName = new ConcurrentHashMap<>();
|
||||
|
||||
// A map by name for QueryResultsRegion instances that have the same name as a Region
|
||||
// in #regionsByName.
|
||||
private final Map<String, QueryResultsRegion> queryResultsRegionsByDuplicateName = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<NavigableRole,EntityDataAccess> entityAccessMap = new ConcurrentHashMap<>();
|
||||
private final Map<NavigableRole,NaturalIdDataAccess> naturalIdAccessMap = new ConcurrentHashMap<>();
|
||||
private final Map<NavigableRole,CollectionDataAccess> collectionAccessMap = new ConcurrentHashMap<>();
|
||||
|
@ -204,6 +209,8 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin
|
|||
|
||||
@Override
|
||||
public Region getRegion(String regionName) {
|
||||
// The Region in regionsByName has precedence over the
|
||||
// QueryResultsRegion in #queryResultsRegionsByDuplicateName
|
||||
return regionsByName.get( regionName );
|
||||
}
|
||||
|
||||
|
@ -488,12 +495,23 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin
|
|||
}
|
||||
|
||||
protected QueryResultsCache makeQueryResultsRegionAccess(String regionName) {
|
||||
final QueryResultsRegion region = (QueryResultsRegion) regionsByName.computeIfAbsent(
|
||||
final Region region = regionsByName.computeIfAbsent(
|
||||
regionName,
|
||||
this::makeQueryResultsRegion
|
||||
);
|
||||
final QueryResultsRegion queryResultsRegion;
|
||||
if ( QueryResultsRegion.class.isInstance( region ) ) {
|
||||
queryResultsRegion = (QueryResultsRegion) region;
|
||||
}
|
||||
else {
|
||||
// There was already a different type of Region with the same name.
|
||||
queryResultsRegion = queryResultsRegionsByDuplicateName.computeIfAbsent(
|
||||
regionName,
|
||||
this::makeQueryResultsRegion
|
||||
);
|
||||
}
|
||||
final QueryResultsCacheImpl regionAccess = new QueryResultsCacheImpl(
|
||||
region,
|
||||
queryResultsRegion,
|
||||
timestampsCache
|
||||
);
|
||||
namedQueryResultsCacheMap.put( regionName, regionAccess );
|
||||
|
@ -502,20 +520,9 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin
|
|||
}
|
||||
|
||||
protected QueryResultsRegion makeQueryResultsRegion(String regionName) {
|
||||
// make sure there is not an existing domain-data region with that name..
|
||||
final Region existing = regionsByName.get( regionName );
|
||||
if ( existing != null ) {
|
||||
if ( !QueryResultsRegion.class.isInstance( existing ) ) {
|
||||
throw new IllegalStateException( "Cannot store both domain-data and query-result-data in the same region [" + regionName );
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "Illegal call to create QueryResultsRegion - one already existed" );
|
||||
}
|
||||
|
||||
return regionFactory.buildQueryResultsRegion( regionName, getSessionFactory() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getCacheRegionNames() {
|
||||
return regionsByName.keySet();
|
||||
|
@ -524,6 +531,10 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin
|
|||
@Override
|
||||
public void evictRegion(String regionName) {
|
||||
getRegion( regionName ).clear();
|
||||
final QueryResultsRegion queryResultsRegionWithDuplicateName = queryResultsRegionsByDuplicateName.get( regionName );
|
||||
if ( queryResultsRegionWithDuplicateName != null ) {
|
||||
queryResultsRegionWithDuplicateName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -545,6 +556,9 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin
|
|||
for ( Region region : regionsByName.values() ) {
|
||||
region.destroy();
|
||||
}
|
||||
for ( Region region : queryResultsRegionsByDuplicateName.values() ) {
|
||||
region.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,9 @@ public interface CacheImplementor extends Service, Cache, org.hibernate.engine.s
|
|||
void prime(Set<DomainDataRegionConfig> cacheRegionConfigs);
|
||||
|
||||
/**
|
||||
* Get a cache Region by name
|
||||
* Get a cache Region by name. If there is both a {@link DomainDataRegion}
|
||||
* and a {@link QueryResultsRegion} with the specified name, then the
|
||||
* {@link DomainDataRegion} will be returned.
|
||||
*
|
||||
* @apiNote It is only valid to call this method after {@link #prime} has
|
||||
* been performed
|
||||
|
|
Loading…
Reference in New Issue