@@ -230,7 +230,6 @@ public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings
230
230
231
231
#region Persisters
232
232
233
- Dictionary < string , ICacheConcurrencyStrategy > caches = new Dictionary < string , ICacheConcurrencyStrategy > ( ) ;
234
233
entityPersisters = new Dictionary < string , IEntityPersister > ( ) ;
235
234
implementorToEntityName = new Dictionary < System . Type , string > ( ) ;
236
235
@@ -239,22 +238,15 @@ public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings
239
238
foreach ( PersistentClass model in cfg . ClassMappings )
240
239
{
241
240
model . PrepareTemporaryTables ( mapping , settings . Dialect ) ;
242
- string cacheRegion = model . RootClazz . CacheRegionName ;
243
- ICacheConcurrencyStrategy cache ;
244
- if ( ! caches . TryGetValue ( cacheRegion , out cache ) )
245
- {
246
- cache =
247
- CacheFactory . CreateCache ( model . CacheConcurrencyStrategy , cacheRegion , model . IsMutable , settings , properties ) ;
248
- if ( cache != null )
249
- {
250
- caches . Add ( cacheRegion , cache ) ;
251
- if ( ! allCacheRegions . TryAdd ( cache . RegionName , cache . Cache ) )
252
- {
253
- throw new HibernateException ( "An item with the same key has already been added to allCacheRegions." ) ;
254
- }
255
- }
256
- }
257
- IEntityPersister cp = PersisterFactory . CreateClassPersister ( model , cache , this , mapping ) ;
241
+ var cacheRegion = model . RootClazz . CacheRegionName ;
242
+ var strategy = model . CacheConcurrencyStrategy ;
243
+ var cache = CacheFactory . CreateCache (
244
+ strategy ,
245
+ cacheRegion ,
246
+ model . IsMutable ,
247
+ settings ,
248
+ GetOrBuild ) ;
249
+ var cp = PersisterFactory . CreateClassPersister ( model , cache , this , mapping ) ;
258
250
entityPersisters [ model . EntityName ] = cp ;
259
251
classMeta [ model . EntityName ] = cp . ClassMetadata ;
260
252
@@ -269,14 +261,14 @@ public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings
269
261
collectionPersisters = new Dictionary < string , ICollectionPersister > ( ) ;
270
262
foreach ( Mapping . Collection model in cfg . CollectionMappings )
271
263
{
272
- ICacheConcurrencyStrategy cache =
273
- CacheFactory . CreateCache ( model . CacheConcurrencyStrategy , model . CacheRegionName , model . Owner . IsMutable , settings ,
274
- properties ) ;
275
- if ( cache != null )
276
- {
277
- allCacheRegions [ cache . RegionName ] = cache . Cache ;
278
- }
279
- ICollectionPersister persister = PersisterFactory . CreateCollectionPersister ( model , cache , this ) ;
264
+ var cacheRegion = model . CacheRegionName ;
265
+ var cache = CacheFactory . CreateCache (
266
+ model . CacheConcurrencyStrategy ,
267
+ cacheRegion ,
268
+ model . Owner . IsMutable ,
269
+ settings ,
270
+ GetOrBuild ) ;
271
+ var persister = PersisterFactory . CreateCollectionPersister ( model , cache , this ) ;
280
272
collectionPersisters [ model . Role ] = persister ;
281
273
IType indexType = persister . IndexType ;
282
274
if ( indexType != null && indexType . IsAssociationType && ! indexType . IsAnyType )
@@ -377,8 +369,15 @@ public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings
377
369
378
370
if ( settings . IsQueryCacheEnabled )
379
371
{
380
- updateTimestampsCache = new UpdateTimestampsCache ( settings , properties ) ;
381
- queryCache = settings . QueryCacheFactory . GetQueryCache ( null , updateTimestampsCache , settings , properties ) ;
372
+ var updateTimestampsCacheName = typeof ( StandardQueryCache ) . Name ;
373
+ updateTimestampsCache = new UpdateTimestampsCache ( GetOrBuild ( updateTimestampsCacheName ) ) ;
374
+ var queryCacheName = typeof ( StandardQueryCache ) . FullName ;
375
+ queryCache = settings . QueryCacheFactory . GetQueryCache (
376
+ queryCacheName ,
377
+ updateTimestampsCache ,
378
+ settings ,
379
+ properties ,
380
+ GetOrBuild ( queryCacheName ) ) ;
382
381
queryCaches = new ConcurrentDictionary < string , Lazy < IQueryCache > > ( ) ;
383
382
}
384
383
else
@@ -1005,6 +1004,25 @@ public ICache GetSecondLevelCacheRegion(string regionName)
1005
1004
return result ;
1006
1005
}
1007
1006
1007
+ /// <summary>
1008
+ /// Get an existing <see cref="ICache"/> or build a new one if not already existing.
1009
+ /// </summary>
1010
+ /// <param name="cacheRegion">The (unprefixed) cache region of the cache to get or build.</param>
1011
+ /// <returns>A cache.</returns>
1012
+ private ICache GetOrBuild ( string cacheRegion )
1013
+ {
1014
+ // If run concurrently for the same region, this may built many caches for the same region.
1015
+ // Currently only GetQueryCache may be run concurrently, and its implementation prevents
1016
+ // concurrent creation call for the same region, so this will not happen.
1017
+ // Otherwise the dictionary will have to be changed for using a lazy, see
1018
+ // https://stackoverflow.com/a/31637510/1178314
1019
+ var prefix = settings . CacheRegionPrefix ;
1020
+ if ( ! string . IsNullOrEmpty ( prefix ) )
1021
+ cacheRegion = prefix + '.' + cacheRegion ;
1022
+ return allCacheRegions . GetOrAdd ( cacheRegion ,
1023
+ cr => settings . CacheProvider . BuildCache ( cr , properties ) ) ;
1024
+ }
1025
+
1008
1026
/// <summary> Statistics SPI</summary>
1009
1027
public IStatisticsImplementor StatisticsImplementor
1010
1028
{
@@ -1033,12 +1051,12 @@ public IQueryCache GetQueryCache(string cacheRegion)
1033
1051
return queryCaches . GetOrAdd (
1034
1052
cacheRegion ,
1035
1053
cr => new Lazy < IQueryCache > (
1036
- ( ) =>
1037
- {
1038
- var currentQueryCache = settings . QueryCacheFactory . GetQueryCache ( cr , updateTimestampsCache , settings , properties ) ;
1039
- allCacheRegions [ currentQueryCache . RegionName ] = currentQueryCache . Cache ;
1040
- return currentQueryCache ;
1041
- } ) ) . Value ;
1054
+ ( ) => settings . QueryCacheFactory . GetQueryCache (
1055
+ cr ,
1056
+ updateTimestampsCache ,
1057
+ settings ,
1058
+ properties ,
1059
+ GetOrBuild ( cr ) ) ) ) . Value ;
1042
1060
}
1043
1061
1044
1062
public void EvictQueries ( )
0 commit comments