From 72fe79a3f2af28150016fc521e65bf9983ba2d94 Mon Sep 17 00:00:00 2001 From: Eric Dalquist Date: Fri, 27 Jan 2012 13:17:49 -0600 Subject: [PATCH] HHH-6974 Addition of NaturalIdRegion SPI Adds NaturalIdRegion to RegionFactory Adds creation of NaturalIdRegions to SessionFactoryImpl setup Basic copy of collection cache region behavior for first pass at naturalId region support in ehcache --- .../org/hibernate/annotations/NaturalId.java | 7 ++ .../internal/CacheDataDescriptionImpl.java | 9 +++ .../internal/NoCachingRegionFactory.java | 6 ++ .../hibernate/cache/spi/RegionFactory.java | 14 ++++ .../DefaultResolveNaturalIdEventListener.java | 80 +++++++++---------- .../internal/SessionFactoryImpl.java | 25 +++++- .../entity/AbstractEntityPersister.java | 5 ++ .../persister/entity/EntityPersister.java | 8 ++ .../tuple/entity/EntityMetamodel.java | 9 +++ .../GoofyPersisterClassProvider.java | 5 ++ .../test/legacy/CustomPersister.java | 5 ++ .../ehcache/AbstractEhcacheRegionFactory.java | 8 ++ .../nonstop/NonstopAccessStrategyFactory.java | 15 +++- .../EhcacheAccessStrategyFactory.java | 12 +++ .../EhcacheAccessStrategyFactoryImpl.java | 38 ++++++++- .../PersisterClassProviderTest.java | 7 +- .../infinispan/InfinispanRegionFactory.java | 9 ++- .../cluster/ClusterAwareRegionFactory.java | 7 ++ .../testing/cache/CachingRegionFactory.java | 9 ++- 19 files changed, 227 insertions(+), 51 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/NaturalId.java b/hibernate-core/src/main/java/org/hibernate/annotations/NaturalId.java index f9993565b7..d589fd2e47 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/NaturalId.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/NaturalId.java @@ -44,4 +44,11 @@ public @interface NaturalId { * @return {@code true} indicates the natural id is mutable; {@code false} (the default) that it is immutable. */ boolean mutable() default false; + + /** + * Should the mapping of this natural id to the primary id be cached + * + * @return {@code true} (the default) indicates the natural id mapping should be cached; {@code false} that the mapping should not be cached. + */ + boolean cache() default true; } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java index 17c801f09c..aa365cb5bf 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java @@ -30,6 +30,7 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.binding.EntityBinding; import org.hibernate.metamodel.binding.PluralAttributeBinding; +import org.hibernate.persister.entity.EntityPersister; import org.hibernate.type.VersionType; /** @@ -90,6 +91,14 @@ public class CacheDataDescriptionImpl implements CacheDataDescription { ); } + public static CacheDataDescriptionImpl decode(EntityPersister persister) { + return new CacheDataDescriptionImpl( + !persister.getEntityMetamodel().hasImmutableNaturalId(), + false, + null + ); + } + private static Comparator getVersionComparator(EntityBinding model ) { Comparator versionComparator = null; if ( model.isVersioned() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/NoCachingRegionFactory.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/NoCachingRegionFactory.java index de22ac93df..46bdf6972c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/NoCachingRegionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/NoCachingRegionFactory.java @@ -30,6 +30,7 @@ import org.hibernate.cache.NoCachingEnabledException; import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.TimestampsRegion; @@ -67,6 +68,11 @@ public class NoCachingRegionFactory implements RegionFactory { throws CacheException { throw new NoCachingEnabledException(); } + + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + throw new NoCachingEnabledException(); + } public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/RegionFactory.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/RegionFactory.java index 8cce5ee857..65f0b217c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/RegionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/RegionFactory.java @@ -106,6 +106,20 @@ public interface RegionFactory extends Service { public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException; + /** + * Build a cache region specialized for storing NaturalId to Primary Key mappings. + * + * @param regionName The name of the region. + * @param properties Configuration properties. + * @param metadata Information regarding the type of data to be cached + * + * @return The built region + * + * @throws CacheException Indicates problems building the region. + */ + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException; + /** * Build a cache region specialized for storing collection data. * diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultResolveNaturalIdEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultResolveNaturalIdEventListener.java index 822cceb504..6ae5ee6027 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultResolveNaturalIdEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultResolveNaturalIdEventListener.java @@ -25,14 +25,17 @@ package org.hibernate.event.internal; import java.io.Serializable; -import org.jboss.logging.Logger; - import org.hibernate.HibernateException; +import org.hibernate.cache.spi.CacheKey; +import org.hibernate.cache.spi.entry.CacheEntry; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.spi.ResolveNaturalIdEvent; import org.hibernate.event.spi.ResolveNaturalIdEventListener; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.pretty.MessageHelper; +import org.jboss.logging.Logger; /** * Defines the default load event listeners used by hibernate for loading entities @@ -141,48 +144,37 @@ public class DefaultResolveNaturalIdEventListener * @return The entity from the second-level cache, or null. */ protected Serializable loadFromSecondLevelCache(final ResolveNaturalIdEvent event) { - - // final SessionImplementor source = event.getSession(); - // - // final boolean useCache = persister.hasCache() - // && source.getCacheMode().isGetEnabled(); - // - // if ( useCache ) { - // - // final SessionFactoryImplementor factory = source.getFactory(); - // - // final CacheKey ck = source.generateCacheKey( - // event.getNaturalIdValues(), - // persister.getIdentifierType(), - // persister.getRootEntityName() - // ); - // Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() ); - // if ( factory.getStatistics().isStatisticsEnabled() ) { - // if ( ce == null ) { - // factory.getStatisticsImplementor().secondLevelCacheMiss( - // persister.getCacheAccessStrategy().getRegion().getName() - // ); - // } - // else { - // factory.getStatisticsImplementor().secondLevelCacheHit( - // persister.getCacheAccessStrategy().getRegion().getName() - // ); - // } - // } - // - // if ( ce != null ) { - // CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory ); - // - // // Entity was found in second-level cache... - // return assembleCacheEntry( - // entry, - // event.getEntityId(), - // persister, - // event - // ); - // } - // } - +// final SessionImplementor source = event.getSession(); +// +// EntityPersister persister = event.getEntityPersister(); +// +// final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled(); +// +// if ( useCache ) { +// +// final SessionFactoryImplementor factory = source.getFactory(); +// +// final CacheKey ck = source.generateCacheKey( event.getNaturalIdValues(), persister.getIdentifierType(), +// persister.getRootEntityName() ); +// Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() ); +// if ( factory.getStatistics().isStatisticsEnabled() ) { +// if ( ce == null ) { +// factory.getStatisticsImplementor().secondLevelCacheMiss( +// persister.getCacheAccessStrategy().getRegion().getName() ); +// } +// else { +// factory.getStatisticsImplementor().secondLevelCacheHit( +// persister.getCacheAccessStrategy().getRegion().getName() ); +// } +// } +// +// if ( ce != null ) { +// CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory ); +// +// // Entity was found in second-level cache... +// return assembleCacheEntry( entry, event.getEntityId(), persister, event ); +// } +// } return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 0121cb7c3b..fec89f611f 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -66,12 +66,14 @@ import org.hibernate.cache.internal.CacheDataDescriptionImpl; import org.hibernate.cache.spi.CacheKey; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.QueryCache; import org.hibernate.cache.spi.Region; import org.hibernate.cache.spi.UpdateTimestampsCache; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; import org.hibernate.cache.spi.access.RegionAccessStrategy; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; @@ -171,7 +173,8 @@ import org.hibernate.type.TypeResolver; public final class SessionFactoryImpl implements SessionFactoryImplementor { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SessionFactoryImpl.class.getName()); + private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId"; + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SessionFactoryImpl.class.getName()); private static final IdentifierGenerator UUID_GENERATOR = UUIDGenerator.buildSessionFactoryUniqueIdentifierGenerator(); private final String name; @@ -356,6 +359,18 @@ public final class SessionFactoryImpl ); entityPersisters.put( model.getEntityName(), cp ); classMeta.put( model.getEntityName(), cp.getClassMetadata() ); + + if ( cp.hasNaturalIdentifier() && cp.isNatrualIdentifierCached() ) { + final String naturalIdCacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName() + NATURAL_ID_CACHE_SUFFIX; + NaturalIdRegionAccessStrategy naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName ); + + if ( naturalIdAccessStrategy == null && settings.isSecondLevelCacheEnabled() ) { + final NaturalIdRegion naturalIdRegion = settings.getRegionFactory().buildNaturalIdRegion( naturalIdCacheRegionName, properties, CacheDataDescriptionImpl.decode( cp ) ); + naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( settings.getRegionFactory().getDefaultAccessType() ); + entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy ); + allCacheRegions.put( naturalIdCacheRegionName, naturalIdRegion ); + } + } } this.classMetadata = Collections.unmodifiableMap(classMeta); @@ -790,6 +805,14 @@ public final class SessionFactoryImpl ); entityPersisters.put( model.getEntity().getName(), cp ); classMeta.put( model.getEntity().getName(), cp.getClassMetadata() ); + + if ( settings.isSecondLevelCacheEnabled() && cp.hasNaturalIdentifier() && cp.isNatrualIdentifierCached() ) { + final String naturalIdCacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails().getCaching().getRegion() + NATURAL_ID_CACHE_SUFFIX; + final NaturalIdRegion naturalIdRegion = settings.getRegionFactory().buildNaturalIdRegion( naturalIdCacheRegionName, properties, CacheDataDescriptionImpl.decode( cp ) ); + final NaturalIdRegionAccessStrategy naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( settings.getRegionFactory().getDefaultAccessType() ); + entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy ); + allCacheRegions.put( naturalIdCacheRegionName, naturalIdRegion ); + } } this.classMetadata = Collections.unmodifiableMap(classMeta); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 1891b426d7..f4bf6d7bd5 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -4601,6 +4601,11 @@ public abstract class AbstractEntityPersister public boolean hasNaturalIdentifier() { return entityMetamodel.hasNaturalIdentifier(); } + + @Override + public boolean isNatrualIdentifierCached() { + return entityMetamodel.isNatrualIdentifierCached(); + } public void setPropertyValue(Object object, String propertyName, Object value) { getEntityTuplizer().setPropertyValue( object, propertyName, value ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java index 68902f11de..b2e1ce1234 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java @@ -31,6 +31,7 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.annotations.NaturalId; import org.hibernate.bytecode.spi.EntityInstrumentationMetadata; import org.hibernate.cache.spi.OptimisticCacheSource; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; @@ -288,6 +289,13 @@ public interface EntityPersister extends OptimisticCacheSource { * @return True if the entity defines a natural id; false otherwise. */ public boolean hasNaturalIdentifier(); + + /** + * Determine whether this entity's natural identifier is cacheable. {@link NaturalId#cache()} + * + * @return True if the natural id is cacheable, false if it is not cacheable or no natural id is defined + */ + public boolean isNatrualIdentifierCached(); /** * If the entity defines a natural id ({@link #hasNaturalIdentifier()}), which diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index ca5b54331b..55c7d4d78b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -112,6 +112,7 @@ public class EntityMetamodel implements Serializable { private final int[] naturalIdPropertyNumbers; private final boolean hasImmutableNaturalId; + private final boolean hasCacheableNaturalId; private boolean lazy; //not final because proxy factory creation can fail private final boolean hasCascades; @@ -257,10 +258,12 @@ public class EntityMetamodel implements Serializable { if (naturalIdNumbers.size()==0) { naturalIdPropertyNumbers = null; hasImmutableNaturalId = false; + hasCacheableNaturalId = false; } else { naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); hasImmutableNaturalId = !foundUpdateableNaturalIdProperty; + hasCacheableNaturalId = true; //TODO how to read the annotation here? } hasInsertGeneratedValues = foundInsertGeneratedValue; @@ -502,10 +505,12 @@ public class EntityMetamodel implements Serializable { if (naturalIdNumbers.size()==0) { naturalIdPropertyNumbers = null; hasImmutableNaturalId = false; + hasCacheableNaturalId = false; } else { naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); hasImmutableNaturalId = !foundUpdateableNaturalIdProperty; + hasCacheableNaturalId = true; //TODO how to read the annotation here? } hasInsertGeneratedValues = foundInsertGeneratedValue; @@ -711,6 +716,10 @@ public class EntityMetamodel implements Serializable { public boolean hasNaturalIdentifier() { return naturalIdPropertyNumbers!=null; } + + public boolean isNatrualIdentifierCached() { + return hasNaturalIdentifier() && hasCacheableNaturalId; + } public boolean hasImmutableNaturalId() { return hasImmutableNaturalId; diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java index 4623291e7e..52c6113b24 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/persister/GoofyPersisterClassProvider.java @@ -235,6 +235,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver { public boolean hasNaturalIdentifier() { return false; } + + @Override + public boolean isNatrualIdentifierCached() { + return false; + } @Override public int[] getNaturalIdentifierProperties() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java index 9ea279f52f..899884b061 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java +++ b/hibernate-core/src/test/java/org/hibernate/test/legacy/CustomPersister.java @@ -563,6 +563,11 @@ public class CustomPersister implements EntityPersister { public boolean hasNaturalIdentifier() { return false; } + + @Override + public boolean isNatrualIdentifierCached() { + return false; + } @Override public boolean hasMutableProperties() { diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java index c381261551..fb53506d2b 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/AbstractEhcacheRegionFactory.java @@ -44,6 +44,7 @@ import org.hibernate.cache.ehcache.management.impl.ProviderMBeanRegistrationHelp import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.TimestampsRegion; @@ -129,6 +130,13 @@ abstract class AbstractEhcacheRegionFactory implements RegionFactory { throws CacheException { return new EhcacheEntityRegion( accessStrategyFactory, getCache( regionName ), settings, metadata, properties ); } + + @Override + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + // TODO Auto-generated method stub + return null; + } /** * {@inheritDoc} diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/nonstop/NonstopAccessStrategyFactory.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/nonstop/NonstopAccessStrategyFactory.java index 54620c4b60..93ab9c897c 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/nonstop/NonstopAccessStrategyFactory.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/nonstop/NonstopAccessStrategyFactory.java @@ -25,10 +25,12 @@ package org.hibernate.cache.ehcache.internal.nonstop; import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion; import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion; +import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion; import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; /** * Implementation of {@link org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory} that takes care of Nonstop cache exceptions using @@ -60,7 +62,18 @@ public class NonstopAccessStrategyFactory implements EhcacheAccessStrategyFactor ); } - /** + @Override + public NaturalIdRegionAccessStrategy createNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion naturalIdRegion, + AccessType accessType) { + return new NonstopAwareNaturalIdRegionAccessStrategy( + actualFactory.createNaturalIdRegionAccessStrategy( + naturalIdRegion, + accessType + ), HibernateNonstopCacheExceptionHandler.getInstance() + ); + } + + /** * {@inheritDoc} */ public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion, diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactory.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactory.java index dbf591ca42..6265cdae58 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactory.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactory.java @@ -25,9 +25,11 @@ package org.hibernate.cache.ehcache.internal.strategy; import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion; import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion; +import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; /** * Factory to create {@link EntityRegionAccessStrategy} @@ -57,5 +59,15 @@ public interface EhcacheAccessStrategyFactory { */ public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion, AccessType accessType); + /** + * Create {@link NaturalIdRegionAccessStrategy} for the input {@link org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion} and {@link AccessType} + * + * @param naturalIdRegion + * @param accessType + * + * @return the created {@link NaturalIdRegionAccessStrategy} + */ + public NaturalIdRegionAccessStrategy createNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion naturalIdRegion, + AccessType accessType); } diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactoryImpl.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactoryImpl.java index ca3b33faa7..5179d4525a 100644 --- a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactoryImpl.java +++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/EhcacheAccessStrategyFactoryImpl.java @@ -23,14 +23,15 @@ */ package org.hibernate.cache.ehcache.internal.strategy; -import org.jboss.logging.Logger; - import org.hibernate.cache.ehcache.EhCacheMessageLogger; import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion; import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion; +import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.jboss.logging.Logger; /** * Class implementing {@link EhcacheAccessStrategyFactory} @@ -111,4 +112,37 @@ public class EhcacheAccessStrategyFactoryImpl implements EhcacheAccessStrategyFa } } + @Override + public NaturalIdRegionAccessStrategy createNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion naturalIdRegion, + AccessType accessType) { + switch ( accessType ) { + case READ_ONLY: + if ( naturalIdRegion.getCacheDataDescription().isMutable() ) { + LOG.readOnlyCacheConfiguredForMutableEntity( naturalIdRegion.getName() ); + } + return new ReadOnlyEhcacheNaturalIdRegionAccessStrategy( + naturalIdRegion, + naturalIdRegion.getSettings() + ); + case READ_WRITE: + return new ReadWriteEhcacheNaturalIdRegionAccessStrategy( + naturalIdRegion, + naturalIdRegion.getSettings() + ); + case NONSTRICT_READ_WRITE: + return new NonStrictReadWriteEhcacheNaturalIdRegionAccessStrategy( + naturalIdRegion, + naturalIdRegion.getSettings() + ); + case TRANSACTIONAL: + return new TransactionalEhcacheNaturalIdRegionAccessStrategy( + naturalIdRegion, naturalIdRegion.getEhcache(), naturalIdRegion + .getSettings() + ); + default: + throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" ); + } + } + + } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/ejb3configuration/PersisterClassProviderTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/ejb3configuration/PersisterClassProviderTest.java index 868cd6507c..bf08183fbc 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/ejb3configuration/PersisterClassProviderTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/ejb3configuration/PersisterClassProviderTest.java @@ -257,8 +257,13 @@ public class PersisterClassProviderTest { public boolean hasNaturalIdentifier() { return false; } - + @Override + public boolean isNatrualIdentifierCached() { + return false; + } + + @Override public int[] getNaturalIdentifierProperties() { return new int[0]; } 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 ab29da4f90..e0eb006258 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 @@ -16,6 +16,7 @@ import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.TimestampsRegion; @@ -194,7 +195,13 @@ public class InfinispanRegionFactory implements RegionFactory { startRegion(region, regionName); return region; } - + + @Override + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + throw new UnsupportedOperationException(); //TODO + } + /** * {@inheritDoc} */ diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java index 2f035d1746..d6842295a7 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java @@ -26,6 +26,7 @@ import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.TimestampsRegion; @@ -101,6 +102,12 @@ public class ClusterAwareRegionFactory implements RegionFactory { CacheDataDescription metadata) throws CacheException { return delegate.buildEntityRegion(regionName, properties, metadata); } + + @Override + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + return delegate.buildNaturalIdRegion( regionName, properties, metadata ); + } public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException { 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 b942455456..05673ad4e6 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 @@ -32,6 +32,7 @@ import org.hibernate.cache.internal.Timestamper; import org.hibernate.cache.spi.CacheDataDescription; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.QueryResultsRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.TimestampsRegion; @@ -85,8 +86,14 @@ public class CachingRegionFactory implements RegionFactory { throws CacheException { return new EntityRegionImpl( regionName, metadata, settings ); } - + @Override + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + return new NaturalIdRegionImpl( regionName, metadata, settings ); + } + + @Override public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { return new CollectionRegionImpl( regionName, metadata, settings );