HHH-6207 Implementing binding of @Cacheable. Changing implementation of Caching to use AccessType enum instead of string

This commit is contained in:
Hardy Ferentschik 2011-05-11 15:12:06 +02:00
parent 3dfeceffe3
commit 850cfda6c3
8 changed files with 144 additions and 44 deletions

View File

@ -23,13 +23,20 @@
*/
package org.hibernate.metamodel;
import javax.persistence.SharedCacheMode;
import org.hibernate.cfg.NamingStrategy;
/**
* @author Steve Ebersole
* @author Hardy Ferentschik
*/
public interface MetadataBuilder {
public MetadataBuilder with(NamingStrategy namingStrategy);
public MetadataBuilder with(SourceProcessingOrder sourceProcessingOrder);
public MetadataBuilder with(SharedCacheMode cacheMode);
public Metadata buildMetadata();
}

View File

@ -69,6 +69,8 @@ public class MetadataSources {
private final EntityResolver entityResolver;
private final NamingStrategy namingStrategy;
private final MetadataBuilderImpl metadataBuilder;
public MetadataSources(BasicServiceRegistry serviceRegistry) {
this( serviceRegistry, EJB3DTDEntityResolver.INSTANCE, EJB3NamingStrategy.INSTANCE );
}
@ -79,6 +81,7 @@ public class MetadataSources {
this.namingStrategy = namingStrategy;
this.jaxbHelper = new JaxbHelper( this );
this.metadataBuilder = new MetadataBuilderImpl( this );
}
public List<JaxbRoot> getJaxbRootList() {
@ -102,7 +105,7 @@ public class MetadataSources {
}
public MetadataBuilder getMetadataBuilder() {
return new MetadataBuilderImpl( this );
return metadataBuilder;
}
public Metadata buildMetadata() {

View File

@ -23,22 +23,25 @@
*/
package org.hibernate.metamodel.binding;
import org.hibernate.cache.spi.access.AccessType;
/**
* Defines the caching settings for an entity.
*
* @author Steve Ebersole
* @author Hardy Ferentschik
*/
public class Caching {
private String region;
private String strategy;
private AccessType accessType;
private boolean cacheLazyProperties;
public Caching() {
}
public Caching(String region, String strategy, boolean cacheLazyProperties) {
public Caching(String region, AccessType accessType, boolean cacheLazyProperties) {
this.region = region;
this.strategy = strategy;
this.accessType = accessType;
this.cacheLazyProperties = cacheLazyProperties;
}
@ -50,12 +53,12 @@ public class Caching {
this.region = region;
}
public String getStrategy() {
return strategy;
public AccessType getAccessType() {
return accessType;
}
public void setStrategy(String strategy) {
this.strategy = strategy;
public void setAccessType(AccessType accessType) {
this.accessType = accessType;
}
public boolean isCacheLazyProperties() {
@ -65,4 +68,15 @@ public class Caching {
public void setCacheLazyProperties(boolean cacheLazyProperties) {
this.cacheLazyProperties = cacheLazyProperties;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "Caching" );
sb.append( "{region='" ).append( region ).append( '\'' );
sb.append( ", accessType=" ).append( accessType );
sb.append( ", cacheLazyProperties=" ).append( cacheLazyProperties );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -34,6 +34,8 @@ import org.hibernate.MappingException;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.annotations.PolymorphismType;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.binding.Caching;
import org.hibernate.metamodel.binding.EntityBinding;
@ -70,7 +72,8 @@ public class EntityBinder {
bindJpaEntityAnnotation( entityBinding );
bindHibernateEntityAnnotation( entityBinding ); // optional hibernate specific @org.hibernate.annotations.Entity
bindWhereFilter( entityBinding );
bindCaching( entityBinding );
bindJpaCaching( entityBinding );
bindHibernateCaching( entityBinding );
schemaName = createSchemaName();
bindTable( entityBinding );
@ -93,41 +96,90 @@ public class EntityBinder {
}
}
private void bindCaching(EntityBinding entityBinding) {
private void bindHibernateCaching(EntityBinding entityBinding) {
AnnotationInstance cacheAnnotation = JandexHelper.getSingleAnnotation(
configuredClass.getClassInfo(), HibernateDotNames.CACHE
);
if ( cacheAnnotation != null ) {
String region;
if ( cacheAnnotation.value( "region" ) != null ) {
region = cacheAnnotation.value( "region" ).asString();
if ( cacheAnnotation == null ) {
return;
}
String region;
if ( cacheAnnotation.value( "region" ) != null ) {
region = cacheAnnotation.value( "region" ).asString();
}
else {
region = entityBinding.getEntity().getName();
}
boolean cacheLazyProperties = true;
if ( cacheAnnotation.value( "include" ) != null ) {
String tmp = cacheAnnotation.value( "include" ).asString();
if ( "all".equalsIgnoreCase( tmp ) ) {
cacheLazyProperties = true;
}
else if ( "non-lazy".equalsIgnoreCase( tmp ) ) {
cacheLazyProperties = false;
}
else {
region = entityBinding.getEntity().getName();
throw new AnnotationException( "Unknown lazy property annotations: " + tmp );
}
}
boolean cacheLazyProperties = true;
if ( cacheAnnotation.value( "include" ) != null ) {
String tmp = cacheAnnotation.value( "include" ).asString();
if ( "all".equalsIgnoreCase( tmp ) ) {
cacheLazyProperties = true;
}
else if ( "non-lazy".equalsIgnoreCase( tmp ) ) {
cacheLazyProperties = false;
}
else {
throw new AnnotationException( "Unknown lazy property annotations: " + tmp );
}
CacheConcurrencyStrategy strategy = CacheConcurrencyStrategy.valueOf(
cacheAnnotation.value( "usage" ).asEnum()
);
Caching caching = new Caching( region, strategy.toAccessType(), cacheLazyProperties );
entityBinding.setCaching( caching );
}
// This does not take care of any inheritance of @Cacheable within a class hierarchy as specified in JPA2.
// This is currently not supported (HF)
private void bindJpaCaching(EntityBinding entityBinding) {
AnnotationInstance cacheAnnotation = JandexHelper.getSingleAnnotation(
configuredClass.getClassInfo(), JPADotNames.CACHEABLE
);
boolean cacheable = true; // true is the default
if ( cacheAnnotation != null && cacheAnnotation.value() != null ) {
cacheable = cacheAnnotation.value().asBoolean();
}
Caching caching = null;
switch ( meta.getSharedCacheMode() ) {
case ALL: {
caching = createCachingForCacheableAnnotation( entityBinding );
break;
}
CacheConcurrencyStrategy strategy = CacheConcurrencyStrategy.valueOf(
cacheAnnotation.value( "usage" ).asEnum()
);
Caching caching = new Caching( region, strategy.toAccessType().getExternalName(), cacheLazyProperties );
case ENABLE_SELECTIVE: {
if ( cacheable ) {
caching = createCachingForCacheableAnnotation( entityBinding );
}
break;
}
case DISABLE_SELECTIVE: {
if ( cacheAnnotation == null || cacheable ) {
caching = createCachingForCacheableAnnotation( entityBinding );
}
break;
}
default: {
// treat both NONE and UNSPECIFIED the same
break;
}
}
if ( caching != null ) {
entityBinding.setCaching( caching );
}
}
private Caching createCachingForCacheableAnnotation(EntityBinding entityBinding) {
String region = entityBinding.getEntity().getName();
RegionFactory regionFactory = meta.getServiceRegistry().getService( RegionFactory.class );
AccessType defaultAccessType = regionFactory.getDefaultAccessType();
return new Caching( region, defaultAccessType, true );
}
private Schema.Name createSchemaName() {
String schema = null;
String catalog = null;

View File

@ -25,6 +25,7 @@ package org.hibernate.metamodel.source.hbm;
import org.hibernate.InvalidMappingException;
import org.hibernate.MappingException;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.mapping.RootClass;
import org.hibernate.metamodel.binding.Caching;
import org.hibernate.metamodel.binding.EntityBinding;
@ -286,9 +287,8 @@ class RootEntityBinder extends AbstractEntityBinder {
return;
}
final String region = cache.getRegion() != null ? cache.getRegion() : entityBinding.getEntity().getName();
final String strategy = cache.getUsage();
final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() );
final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() );
entityBinding.setCaching( new Caching( region, strategy, cacheLazyProps ) );
entityBinding.setCaching( new Caching( region, accessType, cacheLazyProps ) );
}
}

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.metamodel.source.internal;
import javax.persistence.SharedCacheMode;
import org.hibernate.cfg.EJB3NamingStrategy;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.Metadata;
@ -38,6 +40,7 @@ public class MetadataBuilderImpl implements MetadataBuilder {
private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE;
private SourceProcessingOrder sourceProcessingOrder = SourceProcessingOrder.HBM_FIRST;
private SharedCacheMode sharedCacheMode = SharedCacheMode.ENABLE_SELECTIVE;
public MetadataBuilderImpl(MetadataSources sources) {
this.sources = sources;
@ -51,6 +54,10 @@ public class MetadataBuilderImpl implements MetadataBuilder {
return namingStrategy;
}
public SharedCacheMode getSharedCacheMode() {
return sharedCacheMode;
}
public SourceProcessingOrder getSourceProcessingOrder() {
return sourceProcessingOrder;
}
@ -67,6 +74,12 @@ public class MetadataBuilderImpl implements MetadataBuilder {
return this;
}
@Override
public MetadataBuilder with(SharedCacheMode sharedCacheMode) {
this.sharedCacheMode = sharedCacheMode;
return this;
}
@Override
public Metadata buildMetadata() {
return new MetadataImpl( this );

View File

@ -30,6 +30,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.SharedCacheMode;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
@ -40,13 +41,13 @@ import org.hibernate.HibernateException;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.mapping.MetadataSource;
import org.hibernate.metamodel.Metadata;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.SourceProcessingOrder;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.FetchProfile;
import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.metamodel.relational.Database;
import org.hibernate.metamodel.Metadata;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.source.annotation.xml.XMLEntityMappings;
import org.hibernate.metamodel.source.annotations.AnnotationBinder;
import org.hibernate.metamodel.source.annotations.xml.OrmXmlParser;
@ -69,6 +70,7 @@ public class MetadataImpl implements Metadata, MetadataImplementor, Serializable
private final BasicServiceRegistry serviceRegistry;
private final NamingStrategy namingStrategy;
private final SharedCacheMode sharedCacheMode;
private final Database database = new Database();
private Map<String, EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
@ -81,6 +83,7 @@ public class MetadataImpl implements Metadata, MetadataImplementor, Serializable
this.serviceRegistry = metadataSources.getServiceRegistry();
this.namingStrategy = builder.getNamingStrategy();
this.sharedCacheMode = builder.getSharedCacheMode();
final ArrayList<String> processedEntityNames = new ArrayList<String>();
if ( builder.getSourceProcessingOrder() == SourceProcessingOrder.HBM_FIRST ) {
@ -162,6 +165,10 @@ public class MetadataImpl implements Metadata, MetadataImplementor, Serializable
return namingStrategy;
}
public SharedCacheMode getSharedCacheMode() {
return sharedCacheMode;
}
public EntityBinding getEntityBinding(String entityName) {
return entityBindingMap.get( entityName );
}

View File

@ -26,17 +26,18 @@ package org.hibernate.metamodel.source.annotations;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.SharedCacheMode;
import org.junit.Test;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.binding.Caching;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.source.internal.MetadataImpl;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static junit.framework.Assert.assertEquals;
@ -51,30 +52,33 @@ import static junit.framework.Assert.assertNull;
public class CacheBindingTests extends BaseUnitTestCase {
@Test
public void testHibernateCaching() {
EntityBinding binding = getEntityBinding( HibernateCacheEntity.class );
EntityBinding binding = getEntityBinding( HibernateCacheEntity.class, SharedCacheMode.ALL );
assertNotNull( "There should be a cache binding", binding.getCaching() );
Caching caching = binding.getCaching();
assertEquals( "Wrong region", "foo", caching.getRegion() );
assertEquals( "Wrong strategy", "read-write", caching.getStrategy() );
assertEquals( "Wrong strategy", AccessType.READ_WRITE, caching.getAccessType() );
assertEquals( "Wrong lazy properties configuration", false, caching.isCacheLazyProperties() );
}
@Test
@FailureExpected( jiraKey = "HHH-6207", message = "under construction")
public void testJpaCaching() {
EntityBinding binding = getEntityBinding( JpaCacheEntity.class );
EntityBinding binding = getEntityBinding( JpaCacheEntity.class, SharedCacheMode.ALL );
assertNotNull( "There should be a cache binding", binding.getCaching() );
Caching caching = binding.getCaching();
assertEquals( "Wrong region", "CacheBindingTests$JpaCacheEntity", caching.getRegion() );
assertEquals( "Wrong lazy properties configuration", true, caching.isCacheLazyProperties() );
}
@Test
public void testNoCaching() {
EntityBinding binding = getEntityBinding( NoCacheEntity.class );
EntityBinding binding = getEntityBinding( NoCacheEntity.class, SharedCacheMode.NONE );
assertNull( "There should be no cache binding", binding.getCaching() );
}
private EntityBinding getEntityBinding(Class<?> clazz) {
private EntityBinding getEntityBinding(Class<?> clazz, SharedCacheMode cacheMode) {
MetadataSources sources = new MetadataSources( new ServiceRegistryBuilder().buildServiceRegistry() );
sources.addAnnotatedClass( clazz );
sources.getMetadataBuilder().with( cacheMode );
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
return metadata.getEntityBinding( this.getClass().getSimpleName() + "$" + clazz.getSimpleName() );