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 d589fd2e47..1d30f5df7f 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/NaturalId.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/NaturalId.java
@@ -23,17 +23,18 @@
*/
package org.hibernate.annotations;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
/**
* This specifies that a property is part of the natural id of the entity.
*
* @author Nicol�s Lichtmaier
+ * @see NaturalIdCache
*/
@Target( { METHOD, FIELD } )
@Retention( RUNTIME )
@@ -44,11 +45,4 @@ 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/annotations/NaturalIdCache.java b/hibernate-core/src/main/java/org/hibernate/annotations/NaturalIdCache.java
new file mode 100644
index 0000000000..97e62d8966
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/NaturalIdCache.java
@@ -0,0 +1,44 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.annotations;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Add caching strategy for the NaturalId to Id of a root entity that has a natural id
+ *
+ * @author Eric Dalquist
+ * @see NaturalId
+ */
+@Target({TYPE, METHOD, FIELD})
+@Retention(RUNTIME)
+public @interface NaturalIdCache {
+ /** cache region name, defaults to full.entity.Name##NaturalId */
+ String region() default "";
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdRegion.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdRegion.java
new file mode 100644
index 0000000000..de7c8d8c48
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdRegion.java
@@ -0,0 +1,47 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.spi;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+
+/**
+ * Defines the contract for a cache region which will specifically be used to
+ * store naturalId data.
+ *
+ * @author Eric Dalquist
+ */
+public interface NaturalIdRegion extends TransactionalDataRegion {
+
+ /**
+ * Build an access strategy for the requested access type.
+ *
+ * @param accessType The type of access strategy to build; never null.
+ * @return The appropriate strategy contract for accessing this region
+ * for the requested type of access.
+ * @throws org.hibernate.cache.CacheException Usually indicates mis-configuration.
+ */
+ public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException;
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/access/NaturalIdRegionAccessStrategy.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/access/NaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..be0b414224
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/access/NaturalIdRegionAccessStrategy.java
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.spi.access;
+
+import org.hibernate.cache.spi.NaturalIdRegion;
+
+/**
+ * Contract for managing transactional and concurrent access to cached naturalId
+ * data. For cached naturalId data, all modification actions actually just
+ * invalidate the entry(s). The call sequence here is:
+ * {@link #lockItem} -> {@link #remove} -> {@link #unlockItem}
+ *
+ * There is another usage pattern that is used to invalidate entries
+ * after performing "bulk" HQL/SQL operations:
+ * {@link #lockRegion} -> {@link #removeAll} -> {@link #unlockRegion}
+ *
+ * @author Gavin King
+ * @author Steve Ebersole
+ * @author Eric Dalquist
+ */
+public interface NaturalIdRegionAccessStrategy extends RegionAccessStrategy{
+
+ /**
+ * Get the wrapped naturalId cache region
+ *
+ * @return The underlying region
+ */
+ public NaturalIdRegion getRegion();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
index e4dc5098c0..6785739002 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
@@ -34,6 +34,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+
import javax.persistence.Basic;
import javax.persistence.Cacheable;
import javax.persistence.CollectionTable;
@@ -79,8 +80,6 @@ import javax.persistence.TableGenerator;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
-import org.jboss.logging.Logger;
-
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
@@ -112,6 +111,7 @@ import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.MapKeyType;
import org.hibernate.annotations.NaturalId;
+import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.OnDelete;
@@ -167,6 +167,7 @@ import org.hibernate.mapping.SingleTableSubclass;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.UnionSubclass;
+import org.jboss.logging.Logger;
/**
* JSR 175 annotation binder which reads the annotations from classes, applies the
@@ -574,6 +575,7 @@ public final class AnnotationBinder {
entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );
+ entityBinder.setNaturalIdCache( clazzToProcess.getAnnotation( NaturalIdCache.class ) );
//Filters are not allowed on subclasses
if ( !inheritanceState.hasParents() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
index 8645e3d9ac..ae7d076356 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+
import javax.persistence.Access;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
@@ -35,8 +36,6 @@ import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.SecondaryTables;
-import org.jboss.logging.Logger;
-
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
@@ -47,6 +46,7 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Loader;
+import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.annotations.Persister;
import org.hibernate.annotations.PolymorphismType;
@@ -89,6 +89,7 @@ import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.TableOwner;
import org.hibernate.mapping.Value;
+import org.jboss.logging.Logger;
/**
* Stateful holder and processor for binding Entity information
@@ -97,7 +98,8 @@ import org.hibernate.mapping.Value;
*/
public class EntityBinder {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, EntityBinder.class.getName());
-
+ private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId";
+
private String name;
private XClass annotatedClass;
private PersistentClass persistentClass;
@@ -119,6 +121,7 @@ public class EntityBinder {
private java.util.Map secondaryTableJoins = new HashMap();
private String cacheConcurrentStrategy;
private String cacheRegion;
+ private String naturalIdCacheRegion;
private java.util.Map filters = new HashMap();
private InheritanceState inheritanceState;
private boolean ignoreIdAnnotations;
@@ -230,6 +233,7 @@ public class EntityBinder {
rootClass.setCacheRegionName( cacheRegion );
rootClass.setLazyPropertiesCacheable( cacheLazyProperty );
}
+ rootClass.setNaturalIdCacheRegionName( naturalIdCacheRegion );
boolean forceDiscriminatorInSelects = forceDiscriminator == null
? mappings.forceDiscriminatorInSelectsByDefault()
: forceDiscriminator;
@@ -826,6 +830,25 @@ public class EntityBinder {
cacheLazyProperty = true;
}
}
+
+ public void setNaturalIdCache(NaturalIdCache naturalIdCacheAnn) {
+ if ( naturalIdCacheAnn != null ) {
+ if ( BinderHelper.isEmptyAnnotationValue( naturalIdCacheAnn.region() ) ) {
+ if (cacheRegion != null) {
+ naturalIdCacheRegion = cacheRegion + NATURAL_ID_CACHE_SUFFIX;
+ }
+ else {
+ naturalIdCacheRegion = persistentClass.getEntityName() + NATURAL_ID_CACHE_SUFFIX;
+ }
+ }
+ else {
+ naturalIdCacheRegion = naturalIdCacheAnn.region();
+ }
+ }
+ else {
+ naturalIdCacheRegion = null;
+ }
+ }
public static String getCacheConcurrencyStrategy(CacheConcurrencyStrategy strategy) {
org.hibernate.cache.spi.access.AccessType accessType = strategy.toAccessType();
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java
index 2962a26448..cb912c23c4 100644
--- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java
@@ -182,6 +182,14 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
* @return The region
*/
public Region getSecondLevelCacheRegion(String regionName);
+
+ /**
+ * Get a named naturalId cache region
+ *
+ * @param regionName The name of the region to retrieve.
+ * @return The region
+ */
+ public Region getNaturalIdCacheRegion(String regionName);
/**
* Get a map of all the second level cache regions currently maintained in
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 fec89f611f..83ee962e3d 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java
@@ -39,11 +39,10 @@ import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+
import javax.naming.Reference;
import javax.naming.StringRefAddr;
-import org.jboss.logging.Logger;
-
import org.hibernate.AssertionFailure;
import org.hibernate.Cache;
import org.hibernate.ConnectionReleaseMode;
@@ -145,6 +144,7 @@ import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
+import org.jboss.logging.Logger;
/**
@@ -173,7 +173,6 @@ import org.hibernate.type.TypeResolver;
public final class SessionFactoryImpl
implements SessionFactoryImplementor {
- 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();
@@ -360,8 +359,8 @@ 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;
+ if ( cp.hasNaturalIdentifier() && model.getNaturalIdCacheRegionName() != null ) {
+ final String naturalIdCacheRegionName = cacheRegionPrefix + model.getNaturalIdCacheRegionName();
NaturalIdRegionAccessStrategy naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName );
if ( naturalIdAccessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
@@ -805,14 +804,6 @@ 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);
@@ -1643,6 +1634,10 @@ public final class SessionFactoryImpl
return allCacheRegions.get( regionName );
}
+ public Region getNaturalIdCacheRegion(String regionName) {
+ return allCacheRegions.get( regionName );
+ }
+
@SuppressWarnings( {"unchecked"})
public Map getAllSecondLevelCacheRegions() {
return new HashMap( allCacheRegions );
diff --git a/hibernate-core/src/main/java/org/hibernate/jmx/StatisticsService.java b/hibernate-core/src/main/java/org/hibernate/jmx/StatisticsService.java
index 54f75b5069..cba1ef5466 100644
--- a/hibernate-core/src/main/java/org/hibernate/jmx/StatisticsService.java
+++ b/hibernate-core/src/main/java/org/hibernate/jmx/StatisticsService.java
@@ -12,6 +12,7 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.stat.CollectionStatistics;
import org.hibernate.stat.EntityStatistics;
+import org.hibernate.stat.NaturalIdCacheStatistics;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
@@ -227,6 +228,23 @@ public class StatisticsService implements StatisticsServiceMBean {
public long getSecondLevelCachePutCount() {
return stats.getSecondLevelCachePutCount();
}
+
+ public NaturalIdCacheStatistics getNaturalIdCacheStatistics(String regionName) {
+ return stats.getNaturalIdCacheStatistics( regionName );
+ }
+
+ public long getNaturalIdCacheHitCount() {
+ return stats.getNaturalIdCacheHitCount();
+ }
+
+ public long getNaturalIdCacheMissCount() {
+ return stats.getNaturalIdCacheMissCount();
+ }
+
+ public long getNaturalIdCachePutCount() {
+ return stats.getNaturalIdCachePutCount();
+ }
+
/**
* @see StatisticsServiceMBean#getSessionCloseCount()
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
index b8caca7d44..836fe837de 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
@@ -248,6 +248,7 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
public abstract boolean isInherited();
public abstract boolean isPolymorphic();
public abstract boolean isVersioned();
+ public abstract String getNaturalIdCacheRegionName();
public abstract String getCacheConcurrencyStrategy();
public abstract PersistentClass getSuperclass();
public abstract boolean isExplicitPolymorphism();
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java
index 46f2cc4537..e5ebf617ef 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java
@@ -32,6 +32,7 @@ import org.jboss.logging.Logger;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.internal.CoreMessageLogger;
+import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.SingletonIterator;
@@ -52,6 +53,7 @@ public class RootClass extends PersistentClass implements TableOwner {
private boolean polymorphic;
private String cacheConcurrencyStrategy;
private String cacheRegionName;
+ private String naturalIdCacheRegionName;
private boolean lazyPropertiesCacheable = true;
private Value discriminator; //may be final
private boolean mutable = true;
@@ -307,7 +309,15 @@ public class RootClass extends PersistentClass implements TableOwner {
public void setCacheRegionName(String cacheRegionName) {
this.cacheRegionName = cacheRegionName;
}
-
+
+ @Override
+ public String getNaturalIdCacheRegionName() {
+ return naturalIdCacheRegionName;
+ }
+ public void setNaturalIdCacheRegionName(String naturalIdCacheRegionName) {
+ this.naturalIdCacheRegionName = naturalIdCacheRegionName;
+ }
+
@Override
public boolean isLazyPropertiesCacheable() {
return lazyPropertiesCacheable;
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Subclass.java b/hibernate-core/src/main/java/org/hibernate/mapping/Subclass.java
index aacd1e9fab..2536fcd639 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/Subclass.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/Subclass.java
@@ -55,6 +55,11 @@ public class Subclass extends PersistentClass {
return subclassId;
}
+ @Override
+ public String getNaturalIdCacheRegionName() {
+ return getSuperclass().getNaturalIdCacheRegionName();
+ }
+
public String getCacheConcurrencyStrategy() {
return getSuperclass().getCacheConcurrencyStrategy();
}
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 f4bf6d7bd5..f5365248a7 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
@@ -37,8 +37,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.jboss.logging.Logger;
-
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
@@ -122,6 +120,7 @@ import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeHelper;
import org.hibernate.type.VersionType;
+import org.jboss.logging.Logger;
/**
* Basic functionality for persisting an entity via JDBC
@@ -4601,11 +4600,6 @@ 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 b2e1ce1234..afa8b592aa 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
@@ -289,13 +289,6 @@ 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/stat/NaturalIdCacheStatistics.java b/hibernate-core/src/main/java/org/hibernate/stat/NaturalIdCacheStatistics.java
new file mode 100644
index 0000000000..f0eb35dbc9
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/stat/NaturalIdCacheStatistics.java
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.stat;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * NaturalId query statistics
+ *
+ * Note that for a cached natural id, the cache miss is equals to the db count
+ *
+ * @author Eric Dalquist
+ */
+public interface NaturalIdCacheStatistics extends Serializable {
+ long getHitCount();
+
+ long getMissCount();
+
+ long getPutCount();
+
+ long getElementCountInMemory();
+
+ long getElementCountOnDisk();
+
+ long getSizeInMemory();
+
+ Map getEntries();
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/stat/Statistics.java b/hibernate-core/src/main/java/org/hibernate/stat/Statistics.java
index e8b935b0a9..33cd475080 100755
--- a/hibernate-core/src/main/java/org/hibernate/stat/Statistics.java
+++ b/hibernate-core/src/main/java/org/hibernate/stat/Statistics.java
@@ -59,6 +59,14 @@ public interface Statistics {
*/
public SecondLevelCacheStatistics getSecondLevelCacheStatistics(String regionName);
+ /**
+ * Natural id cache statistics per region
+ *
+ * @param regionName region name
+ * @return NaturalIdCacheStatistics
+ */
+ public NaturalIdCacheStatistics getNaturalIdCacheStatistics(String regionName);
+
/**
* Query statistics from query string (HQL or SQL)
*
@@ -123,6 +131,18 @@ public interface Statistics {
* Get the global number of cacheable queries put in cache
*/
public long getQueryCachePutCount();
+ /**
+ * Get the global number of cached naturalId lookups successfully retrieved from cache
+ */
+ public long getNaturalIdCacheHitCount();
+ /**
+ * Get the global number of cached naturalId lookups *not* found in cache
+ */
+ public long getNaturalIdCacheMissCount();
+ /**
+ * Get the global number of cacheable naturalId lookups put in cache
+ */
+ public long getNaturalIdCachePutCount();
/**
* Get the global number of timestamps successfully retrieved from cache
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentNaturalIdCacheStatisticsImpl.java b/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentNaturalIdCacheStatisticsImpl.java
new file mode 100644
index 0000000000..e60d456bb0
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentNaturalIdCacheStatisticsImpl.java
@@ -0,0 +1,112 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.stat.internal;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.hibernate.cache.spi.CacheKey;
+import org.hibernate.cache.spi.Region;
+import org.hibernate.stat.NaturalIdCacheStatistics;
+
+/**
+ * Second level cache statistics of a specific region
+ *
+ * @author Alex Snaps
+ */
+public class ConcurrentNaturalIdCacheStatisticsImpl extends CategorizedStatistics implements NaturalIdCacheStatistics {
+ private final transient Region region;
+ private AtomicLong hitCount = new AtomicLong();
+ private AtomicLong missCount = new AtomicLong();
+ private AtomicLong putCount = new AtomicLong();
+
+ ConcurrentNaturalIdCacheStatisticsImpl(Region region) {
+ super( region.getName() );
+ this.region = region;
+ }
+
+ public long getHitCount() {
+ return hitCount.get();
+ }
+
+ public long getMissCount() {
+ return missCount.get();
+ }
+
+ public long getPutCount() {
+ return putCount.get();
+ }
+
+ public long getElementCountInMemory() {
+ return region.getElementCountInMemory();
+ }
+
+ public long getElementCountOnDisk() {
+ return region.getElementCountOnDisk();
+ }
+
+ public long getSizeInMemory() {
+ return region.getSizeInMemory();
+ }
+
+ public Map getEntries() {
+ Map map = new HashMap();
+ Iterator iter = region.toMap().entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry me = (Map.Entry) iter.next();
+ map.put(((CacheKey) me.getKey()).getKey(), me.getValue());
+ }
+ return map;
+ }
+
+ public String toString() {
+ StringBuilder buf = new StringBuilder()
+ .append("NaturalIdCacheStatistics")
+ .append("[hitCount=").append(this.hitCount)
+ .append(",missCount=").append(this.missCount)
+ .append(",putCount=").append(this.putCount);
+ //not sure if this would ever be null but wanted to be careful
+ if (region != null) {
+ buf.append(",elementCountInMemory=").append(this.getElementCountInMemory())
+ .append(",elementCountOnDisk=").append(this.getElementCountOnDisk())
+ .append(",sizeInMemory=").append(this.getSizeInMemory());
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ void incrementHitCount() {
+ hitCount.getAndIncrement();
+ }
+
+ void incrementMissCount() {
+ missCount.getAndIncrement();
+ }
+
+ void incrementPutCount() {
+ putCount.getAndIncrement();
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentStatisticsImpl.java b/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentStatisticsImpl.java
index 4871a7608c..acf6a9377b 100644
--- a/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentStatisticsImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/stat/internal/ConcurrentStatisticsImpl.java
@@ -27,8 +27,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
-import org.jboss.logging.Logger;
-
import org.hibernate.cache.spi.Region;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreMessageLogger;
@@ -36,9 +34,11 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.service.Service;
import org.hibernate.stat.CollectionStatistics;
import org.hibernate.stat.EntityStatistics;
+import org.hibernate.stat.NaturalIdCacheStatistics;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.spi.StatisticsImplementor;
+import org.jboss.logging.Logger;
/**
* Implementation of {@link org.hibernate.stat.Statistics} based on the {@link java.util.concurrent} package.
@@ -76,6 +76,10 @@ public class ConcurrentStatisticsImpl implements StatisticsImplementor, Service
private AtomicLong secondLevelCacheHitCount = new AtomicLong();
private AtomicLong secondLevelCacheMissCount = new AtomicLong();
private AtomicLong secondLevelCachePutCount = new AtomicLong();
+
+ private AtomicLong naturalIdCacheHitCount = new AtomicLong();
+ private AtomicLong naturalIdCacheMissCount = new AtomicLong();
+ private AtomicLong naturalIdCachePutCount = new AtomicLong();
private AtomicLong queryExecutionCount = new AtomicLong();
private AtomicLong queryExecutionMaxTime = new AtomicLong();
@@ -93,6 +97,10 @@ public class ConcurrentStatisticsImpl implements StatisticsImplementor, Service
private AtomicLong optimisticFailureCount = new AtomicLong();
+ /**
+ * natural id cache statistics per region
+ */
+ private final ConcurrentMap naturalIdCacheStatistics = new ConcurrentHashMap();
/**
* second level cache statistics per region
*/
@@ -127,6 +135,10 @@ public class ConcurrentStatisticsImpl implements StatisticsImplementor, Service
secondLevelCacheHitCount.set( 0 );
secondLevelCacheMissCount.set( 0 );
secondLevelCachePutCount.set( 0 );
+
+ naturalIdCacheHitCount.set( 0 );
+ naturalIdCacheMissCount.set( 0 );
+ naturalIdCachePutCount.set( 0 );
sessionCloseCount.set( 0 );
sessionOpenCount.set( 0 );
@@ -282,6 +294,31 @@ public class ConcurrentStatisticsImpl implements StatisticsImplementor, Service
collectionRemoveCount.getAndIncrement();
( (ConcurrentCollectionStatisticsImpl) getCollectionStatistics( role ) ).incrementRemoveCount();
}
+
+
+ @Override
+ public NaturalIdCacheStatistics getNaturalIdCacheStatistics(String regionName) {
+ ConcurrentNaturalIdCacheStatisticsImpl nics =
+ (ConcurrentNaturalIdCacheStatisticsImpl) naturalIdCacheStatistics.get( regionName );
+
+ if ( nics == null ) {
+ if ( sessionFactory == null ) {
+ return null;
+ }
+ Region region = sessionFactory.getNaturalIdCacheRegion( regionName );
+ if ( region == null ) {
+ return null;
+ }
+ nics = new ConcurrentNaturalIdCacheStatisticsImpl( region );
+ ConcurrentNaturalIdCacheStatisticsImpl previous;
+ if ( ( previous = (ConcurrentNaturalIdCacheStatisticsImpl) naturalIdCacheStatistics.putIfAbsent(
+ regionName, nics
+ ) ) != null ) {
+ nics = previous;
+ }
+ }
+ return nics;
+ }
/**
* Second level cache statistics per region
@@ -326,6 +363,24 @@ public class ConcurrentStatisticsImpl implements StatisticsImplementor, Service
secondLevelCacheMissCount.getAndIncrement();
( (ConcurrentSecondLevelCacheStatisticsImpl) getSecondLevelCacheStatistics( regionName ) ).incrementMissCount();
}
+
+ @Override
+ public void naturalIdCachePut(String regionName) {
+ naturalIdCachePutCount.getAndIncrement();
+ ( (ConcurrentNaturalIdCacheStatisticsImpl) getNaturalIdCacheStatistics( regionName ) ).incrementPutCount();
+ }
+
+ @Override
+ public void naturalIdCacheHit(String regionName) {
+ naturalIdCacheHitCount.getAndIncrement();
+ ( (ConcurrentNaturalIdCacheStatisticsImpl) getNaturalIdCacheStatistics( regionName ) ).incrementHitCount();
+ }
+
+ @Override
+ public void naturalIdCacheMiss(String regionName) {
+ naturalIdCacheMissCount.getAndIncrement();
+ ( (ConcurrentNaturalIdCacheStatisticsImpl) getNaturalIdCacheStatistics( regionName ) ).incrementMissCount();
+ }
@SuppressWarnings({ "UnnecessaryBoxing" })
public void queryExecuted(String hql, int rows, long time) {
@@ -515,6 +570,21 @@ public class ConcurrentStatisticsImpl implements StatisticsImplementor, Service
public long getSecondLevelCachePutCount() {
return secondLevelCachePutCount.get();
}
+
+ @Override
+ public long getNaturalIdCacheHitCount() {
+ return naturalIdCacheHitCount.get();
+ }
+
+ @Override
+ public long getNaturalIdCacheMissCount() {
+ return naturalIdCacheMissCount.get();
+ }
+
+ @Override
+ public long getNaturalIdCachePutCount() {
+ return naturalIdCachePutCount.get();
+ }
/**
* @return session closing
diff --git a/hibernate-core/src/main/java/org/hibernate/stat/spi/StatisticsImplementor.java b/hibernate-core/src/main/java/org/hibernate/stat/spi/StatisticsImplementor.java
index a9c1c6cb07..cff7ad444e 100644
--- a/hibernate-core/src/main/java/org/hibernate/stat/spi/StatisticsImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/stat/spi/StatisticsImplementor.java
@@ -25,6 +25,7 @@ package org.hibernate.stat.spi;
import org.hibernate.service.Service;
import org.hibernate.stat.Statistics;
+import org.hibernate.stat.internal.ConcurrentSecondLevelCacheStatisticsImpl;
/**
* Statistics SPI for the Hibernate core. This is essentially the "statistic collector" API, its the contract
@@ -171,6 +172,27 @@ public interface StatisticsImplementor extends Statistics, Service {
* @param regionName The name of the cache region
*/
public void secondLevelCacheMiss(String regionName);
+
+ /**
+ * Callback indicating a put into natural id cache.
+ *
+ * @param regionName The name of the cache region
+ */
+ public void naturalIdCachePut(String regionName);
+
+ /**
+ * Callback indicating a get from natural id cache resulted in a hit.
+ *
+ * @param regionName The name of the cache region
+ */
+ public void naturalIdCacheHit(String regionName);
+
+ /**
+ * Callback indicating a get from natural id cache resulted in a miss.
+ *
+ * @param regionName The name of the cache region
+ */
+ public void naturalIdCacheMiss(String regionName);
/**
* Callback indicating a put into the query cache.
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 55c7d4d78b..d8a4d3f77b 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
@@ -263,7 +263,7 @@ public class EntityMetamodel implements Serializable {
else {
naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers);
hasImmutableNaturalId = !foundUpdateableNaturalIdProperty;
- hasCacheableNaturalId = true; //TODO how to read the annotation here?
+ hasCacheableNaturalId = persistentClass.getNaturalIdCacheRegionName() != null;
}
hasInsertGeneratedValues = foundInsertGeneratedValue;
@@ -510,7 +510,7 @@ public class EntityMetamodel implements Serializable {
else {
naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers);
hasImmutableNaturalId = !foundUpdateableNaturalIdProperty;
- hasCacheableNaturalId = true; //TODO how to read the annotation here?
+ hasCacheableNaturalId = false; //See previous TODO and HHH-6354
}
hasInsertGeneratedValues = foundInsertGeneratedValue;
diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/annotations/naturalid/NaturalIdTest.java b/hibernate-core/src/matrix/java/org/hibernate/test/annotations/naturalid/NaturalIdTest.java
index bfcf3d20da..49f6e0a417 100644
--- a/hibernate-core/src/matrix/java/org/hibernate/test/annotations/naturalid/NaturalIdTest.java
+++ b/hibernate-core/src/matrix/java/org/hibernate/test/annotations/naturalid/NaturalIdTest.java
@@ -23,11 +23,14 @@
*/
package org.hibernate.test.annotations.naturalid;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import java.util.List;
-import org.junit.Test;
-
import org.hibernate.Criteria;
+import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
@@ -35,9 +38,7 @@ import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.stat.Statistics;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
/**
* Test case for NaturalId annotation
@@ -112,6 +113,53 @@ public class NaturalIdTest extends BaseCoreFunctionalTestCase {
s.close();
}
+ @Test
+ public void testNaturalIdLoaderCached() {
+ saveSomeCitizens();
+
+ Session s = openSession();
+ Transaction tx = s.beginTransaction();
+ State france = ( State ) s.load( State.class, 2 );
+ final NaturalIdLoadAccess naturalIdLoader = s.byNaturalId( Citizen.class );
+ naturalIdLoader.using( "ssn", "1234" ).using( "state", france );
+
+ Statistics stats = sessionFactory().getStatistics();
+ stats.setStatisticsEnabled( true );
+ stats.clear();
+ assertEquals(
+ "Cache hits should be empty", 0, stats
+ .getQueryCacheHitCount()
+ );
+
+ // first query
+ Citizen citizen = (Citizen)naturalIdLoader.load();
+ assertNotNull( citizen );
+ assertEquals(
+ "Cache hits should be empty", 0, stats
+ .getNaturalIdCacheHitCount()
+ );
+ assertEquals(
+ "First load should be a miss", 1, stats
+ .getNaturalIdCacheMissCount()
+ );
+ assertEquals(
+ "Query result should be added to cache", 1, stats
+ .getNaturalIdCachePutCount()
+ );
+
+ // query a second time - result should be cached
+ citizen = (Citizen)naturalIdLoader.load();
+ assertNotNull( citizen );
+ assertEquals(
+ "Cache hits should be empty", 1, stats
+ .getNaturalIdCacheHitCount()
+ );
+
+ // cleanup
+ tx.rollback();
+ s.close();
+ }
+
@Test
public void testNaturalIdUncached() {
saveSomeCitizens();
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 52c6113b24..4623291e7e 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,11 +235,6 @@ 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 899884b061..9ea279f52f 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,11 +563,6 @@ 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/internal/nonstop/NonstopAwareNaturalIdRegionAccessStrategy.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/nonstop/NonstopAwareNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..f1708801f1
--- /dev/null
+++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/nonstop/NonstopAwareNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,227 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.ehcache.internal.nonstop;
+
+import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cache.spi.access.SoftLock;
+
+/**
+ * Implementation of {@link NaturalIdRegionAccessStrategy} that handles {@link NonStopCacheException} using
+ * {@link HibernateNonstopCacheExceptionHandler}
+ *
+ * @author Abhishek Sanoujam
+ * @author Alex Snaps
+ */
+public class NonstopAwareNaturalIdRegionAccessStrategy implements NaturalIdRegionAccessStrategy {
+
+ private final NaturalIdRegionAccessStrategy actualStrategy;
+ private final HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler;
+
+ /**
+ * Constructor accepting the actual {@link NaturalIdRegionAccessStrategy} and the {@link HibernateNonstopCacheExceptionHandler}
+ *
+ * @param actualStrategy
+ * @param hibernateNonstopExceptionHandler
+ */
+ public NonstopAwareNaturalIdRegionAccessStrategy(NaturalIdRegionAccessStrategy actualStrategy,
+ HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler) {
+ this.actualStrategy = actualStrategy;
+ this.hibernateNonstopExceptionHandler = hibernateNonstopExceptionHandler;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#getRegion()
+ */
+ public NaturalIdRegion getRegion() {
+ return actualStrategy.getRegion();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evict(java.lang.Object)
+ */
+ public void evict(Object key) throws CacheException {
+ try {
+ actualStrategy.evict( key );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evictAll()
+ */
+ public void evictAll() throws CacheException {
+ try {
+ actualStrategy.evictAll();
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#get(java.lang.Object, long)
+ */
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ try {
+ return actualStrategy.get( key, txTimestamp );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
+ */
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ try {
+ return actualStrategy.lockItem( key, version );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockRegion()
+ */
+ public SoftLock lockRegion() throws CacheException {
+ try {
+ return actualStrategy.lockRegion();
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object,
+ * boolean)
+ */
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
+ try {
+ return actualStrategy.putFromLoad( key, value, txTimestamp, version, minimalPutOverride );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)
+ */
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+ try {
+ return actualStrategy.putFromLoad( key, value, txTimestamp, version );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#remove(java.lang.Object)
+ */
+ public void remove(Object key) throws CacheException {
+ try {
+ actualStrategy.remove( key );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#removeAll()
+ */
+ public void removeAll() throws CacheException {
+ try {
+ actualStrategy.removeAll();
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
+ */
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ try {
+ actualStrategy.unlockItem( key, lock );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockRegion(org.hibernate.cache.spi.access.SoftLock)
+ */
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ try {
+ actualStrategy.unlockRegion( lock );
+ }
+ catch ( NonStopCacheException nonStopCacheException ) {
+ hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
+ }
+ }
+
+}
diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/regions/EhcacheNaturalIdRegion.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/regions/EhcacheNaturalIdRegion.java
new file mode 100644
index 0000000000..92d7c9d227
--- /dev/null
+++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/regions/EhcacheNaturalIdRegion.java
@@ -0,0 +1,66 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+package org.hibernate.cache.ehcache.internal.regions;
+
+import java.util.Properties;
+
+import net.sf.ehcache.Ehcache;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
+import org.hibernate.cache.spi.CacheDataDescription;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cfg.Settings;
+
+/**
+ * A collection region specific wrapper around an Ehcache instance.
+ *
+ * This implementation returns Ehcache specific access strategy instances for all the non-transactional access types. Transactional access
+ * is not supported.
+ *
+ * @author Chris Dennis
+ * @author Abhishek Sanoujam
+ * @author Alex Snaps
+ */
+public class EhcacheNaturalIdRegion extends EhcacheTransactionalDataRegion implements NaturalIdRegion {
+
+
+ /**
+ * Constructs an EhcacheNaturalIdRegion around the given underlying cache.
+ *
+ * @param accessStrategyFactory
+ */
+ public EhcacheNaturalIdRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Settings settings,
+ CacheDataDescription metadata, Properties properties) {
+ super( accessStrategyFactory, underlyingCache, settings, metadata, properties );
+ }
+
+ @Override
+ public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+ return accessStrategyFactory.createNaturalIdRegionAccessStrategy( this, accessType );
+ }
+}
\ No newline at end of file
diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/NonStrictReadWriteEhcacheNaturalIdRegionAccessStrategy.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/NonStrictReadWriteEhcacheNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..cbcf454aa0
--- /dev/null
+++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/NonStrictReadWriteEhcacheNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,99 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.ehcache.internal.strategy;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Ehcache specific non-strict read/write NaturalId region access strategy
+ *
+ * @author Chris Dennis
+ * @author Alex Snaps
+ */
+public class NonStrictReadWriteEhcacheNaturalIdRegionAccessStrategy
+ extends AbstractEhcacheAccessStrategy
+ implements NaturalIdRegionAccessStrategy {
+
+ /**
+ * Create a non-strict read/write access strategy accessing the given NaturalId region.
+ */
+ public NonStrictReadWriteEhcacheNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion region, Settings settings) {
+ super( region, settings );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NaturalIdRegion getRegion() {
+ return region;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ return region.get( key );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
+ if ( minimalPutOverride && region.contains( key ) ) {
+ return false;
+ }
+ else {
+ region.put( key, value );
+ return true;
+ }
+ }
+
+ /**
+ * Since this is a non-strict read/write strategy item locking is not used.
+ */
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ /**
+ * Since this is a non-strict read/write strategy item locking is not used.
+ */
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ region.remove( key );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(Object key) throws CacheException {
+ region.remove( key );
+ }
+}
diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/ReadOnlyEhcacheNaturalIdRegionAccessStrategy.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/ReadOnlyEhcacheNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..fe497383e3
--- /dev/null
+++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/ReadOnlyEhcacheNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,93 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.ehcache.internal.strategy;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Ehcache specific read-only NaturalId region access strategy
+ *
+ * @author Chris Dennis
+ * @author Alex Snaps
+ */
+public class ReadOnlyEhcacheNaturalIdRegionAccessStrategy
+ extends AbstractEhcacheAccessStrategy
+ implements NaturalIdRegionAccessStrategy {
+
+ /**
+ * Create a read-only access strategy accessing the given NaturalId region.
+ */
+ public ReadOnlyEhcacheNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion region, Settings settings) {
+ super( region, settings );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NaturalIdRegion getRegion() {
+ return region;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ return region.get( key );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
+ if ( minimalPutOverride && region.contains( key ) ) {
+ return false;
+ }
+ else {
+ region.put( key, value );
+ return true;
+ }
+ }
+
+ /**
+ * Throws UnsupportedOperationException since this cache is read-only
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public SoftLock lockItem(Object key, Object version) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException( "Can't write to a readonly object" );
+ }
+
+ /**
+ * A no-op since this cache is read-only
+ */
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ //throw new UnsupportedOperationException("Can't write to a readonly object");
+ }
+}
diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/ReadWriteEhcacheNaturalIdRegionAccessStrategy.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/ReadWriteEhcacheNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..0384da7789
--- /dev/null
+++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/ReadWriteEhcacheNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,54 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.ehcache.internal.strategy;
+
+import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Ehcache specific read/write NaturalId region access strategy
+ *
+ * @author Chris Dennis
+ * @author Alex Snaps
+ */
+public class ReadWriteEhcacheNaturalIdRegionAccessStrategy
+ extends AbstractReadWriteEhcacheAccessStrategy
+ implements NaturalIdRegionAccessStrategy {
+
+ /**
+ * Create a read/write access strategy accessing the given NaturalId region.
+ */
+ public ReadWriteEhcacheNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion region, Settings settings) {
+ super( region, settings );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NaturalIdRegion getRegion() {
+ return region;
+ }
+}
\ No newline at end of file
diff --git a/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/TransactionalEhcacheNaturalIdRegionAccessStrategy.java b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/TransactionalEhcacheNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..42e30c9046
--- /dev/null
+++ b/hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/strategy/TransactionalEhcacheNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,127 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.ehcache.internal.strategy;
+
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.Element;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.ehcache.internal.regions.EhcacheNaturalIdRegion;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.hibernate.cfg.Settings;
+
+/**
+ * JTA NaturalIdRegionAccessStrategy.
+ *
+ * @author Chris Dennis
+ * @author Ludovic Orban
+ * @author Alex Snaps
+ */
+public class TransactionalEhcacheNaturalIdRegionAccessStrategy
+ extends AbstractEhcacheAccessStrategy
+ implements NaturalIdRegionAccessStrategy {
+
+ private final Ehcache ehcache;
+
+ /**
+ * Construct a new collection region access strategy.
+ *
+ * @param region the Hibernate region.
+ * @param ehcache the cache.
+ * @param settings the Hibernate settings.
+ */
+ public TransactionalEhcacheNaturalIdRegionAccessStrategy(EhcacheNaturalIdRegion region, Ehcache ehcache, Settings settings) {
+ super( region, settings );
+ this.ehcache = ehcache;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ try {
+ Element element = ehcache.get( key );
+ return element == null ? null : element.getObjectValue();
+ }
+ catch ( net.sf.ehcache.CacheException e ) {
+ throw new CacheException( e );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public NaturalIdRegion getRegion() {
+ return region;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean putFromLoad(Object key, Object value, long txTimestamp,
+ Object version, boolean minimalPutOverride) throws CacheException {
+ try {
+ if ( minimalPutOverride && ehcache.get( key ) != null ) {
+ return false;
+ }
+ //OptimisticCache? versioning?
+ ehcache.put( new Element( key, value ) );
+ return true;
+ }
+ catch ( net.sf.ehcache.CacheException e ) {
+ throw new CacheException( e );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(Object key) throws CacheException {
+ try {
+ ehcache.remove( key );
+ }
+ catch ( net.sf.ehcache.CacheException e ) {
+ throw new CacheException( e );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ // no-op
+ }
+
+}
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 bf08183fbc..548c28bc7b 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
@@ -258,11 +258,6 @@ public class PersisterClassProviderTest {
return false;
}
- @Override
- public boolean isNatrualIdentifierCached() {
- return false;
- }
-
@Override
public int[] getNaturalIdentifierProperties() {
return new int[0];
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
new file mode 100644
index 0000000000..ca0fd82902
--- /dev/null
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/BaseNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,53 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.testing.cache;
+
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+
+/**
+ * @author Eric Dalquist
+ */
+class BaseNaturalIdRegionAccessStrategy extends BaseRegionAccessStrategy implements NaturalIdRegionAccessStrategy {
+ private final NaturalIdRegionImpl region;
+
+ @Override
+ protected BaseGeneralDataRegion getInternalRegion() {
+ return region;
+ }
+
+ @Override
+ protected boolean isDefaultMinimalPutOverride() {
+ return region.getSettings().isMinimalPutsEnabled();
+ }
+
+ @Override
+ public NaturalIdRegion getRegion() {
+ return region;
+ }
+
+ BaseNaturalIdRegionAccessStrategy(NaturalIdRegionImpl region) {
+ this.region = region;
+ }
+}
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
new file mode 100644
index 0000000000..570f83a0c4
--- /dev/null
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/NaturalIdRegionImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.testing.cache;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.CacheDataDescription;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cfg.Settings;
+import org.hibernate.internal.CoreMessageLogger;
+import org.jboss.logging.Logger;
+
+/**
+ * @author Eric Dalquist
+ */
+class NaturalIdRegionImpl extends BaseTransactionalDataRegion implements NaturalIdRegion {
+ private static final CoreMessageLogger LOG = Logger.getMessageLogger(
+ CoreMessageLogger.class, NaturalIdRegionImpl.class.getName()
+ );
+ private final Settings settings;
+ NaturalIdRegionImpl(String name, CacheDataDescription metadata, Settings settings) {
+ super( name, metadata );
+ this.settings=settings;
+ }
+
+ public Settings getSettings() {
+ return settings;
+ }
+
+ @Override
+ public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+ switch ( accessType ) {
+ case READ_ONLY:
+ if ( getCacheDataDescription().isMutable() ) {
+ LOG.warnf( "read-only cache configured for mutable collection [ %s ]", getName() );
+ }
+ return new ReadOnlyNaturalIdRegionAccessStrategy( this );
+ case READ_WRITE:
+ return new ReadWriteNaturalIdRegionAccessStrategy( this );
+ case NONSTRICT_READ_WRITE:
+ return new NonstrictReadWriteNaturalIdRegionAccessStrategy( this );
+ case TRANSACTIONAL:
+ return new TransactionalNaturalIdRegionAccessStrategy( this );
+// throw new UnsupportedOperationException( "doesn't support this access strategy" );
+ default:
+ throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
+ }
+ }
+
+
+}
diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/NonstrictReadWriteNaturalIdRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/NonstrictReadWriteNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..381971908c
--- /dev/null
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/NonstrictReadWriteNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.testing.cache;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.SoftLock;
+
+/**
+ * @author Eric Dalquist
+ */
+class NonstrictReadWriteNaturalIdRegionAccessStrategy extends BaseNaturalIdRegionAccessStrategy {
+ NonstrictReadWriteNaturalIdRegionAccessStrategy(NaturalIdRegionImpl region) {
+ super( region );
+ }
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ evict( key );
+ }
+
+ @Override
+ public void remove(Object key) throws CacheException {
+ evict( key );
+ }
+}
diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadOnlyNaturalIdRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadOnlyNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..d8268e5260
--- /dev/null
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadOnlyNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.testing.cache;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.hibernate.internal.CoreMessageLogger;
+
+/**
+ * @author Eric Dalquist
+ */
+class ReadOnlyNaturalIdRegionAccessStrategy extends BaseNaturalIdRegionAccessStrategy {
+ private static final CoreMessageLogger LOG = Logger.getMessageLogger(
+ CoreMessageLogger.class, ReadOnlyNaturalIdRegionAccessStrategy.class.getName()
+ );
+
+ ReadOnlyNaturalIdRegionAccessStrategy(NaturalIdRegionImpl region) {
+ super( region );
+ }
+
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ LOG.invalidEditOfReadOnlyItem( key );
+ }
+
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ LOG.invalidEditOfReadOnlyItem( key );
+ throw new UnsupportedOperationException( "Can't write to a readonly object" );
+ }
+
+
+
+}
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
new file mode 100644
index 0000000000..d2092e1c5b
--- /dev/null
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/ReadWriteNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010-2011, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.testing.cache;
+
+import java.util.Comparator;
+
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+
+/**
+ * @author Eric Dalquist
+ */
+class ReadWriteNaturalIdRegionAccessStrategy extends AbstractReadWriteAccessStrategy
+ implements NaturalIdRegionAccessStrategy {
+
+ private final NaturalIdRegionImpl region;
+
+ ReadWriteNaturalIdRegionAccessStrategy(NaturalIdRegionImpl region) {
+ this.region = region;
+ }
+
+ @Override
+ Comparator getVersionComparator() {
+ return region.getCacheDataDescription().getVersionComparator();
+ }
+
+ @Override
+ protected BaseGeneralDataRegion getInternalRegion() {
+ return region;
+ }
+
+ @Override
+ protected boolean isDefaultMinimalPutOverride() {
+ return region.getSettings().isMinimalPutsEnabled();
+ }
+
+ @Override
+ public NaturalIdRegion getRegion() {
+ return region;
+ }
+}
diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/cache/TransactionalNaturalIdRegionAccessStrategy.java b/hibernate-testing/src/main/java/org/hibernate/testing/cache/TransactionalNaturalIdRegionAccessStrategy.java
new file mode 100644
index 0000000000..625941399d
--- /dev/null
+++ b/hibernate-testing/src/main/java/org/hibernate/testing/cache/TransactionalNaturalIdRegionAccessStrategy.java
@@ -0,0 +1,25 @@
+package org.hibernate.testing.cache;
+
+import org.hibernate.cache.CacheException;
+
+/**
+ * @author Eric Dalquist
+ */
+class TransactionalNaturalIdRegionAccessStrategy extends BaseNaturalIdRegionAccessStrategy {
+ TransactionalNaturalIdRegionAccessStrategy(NaturalIdRegionImpl region) {
+ super( region );
+ }
+
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(Object key) throws CacheException {
+ evict( key );
+ }
+
+
+}