HHH-12146 - Support enabling caching at any level within a mapped hierarchy
This commit is contained in:
parent
6edff69101
commit
59c3baae32
|
@ -61,7 +61,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
for ( Queryable persister : affectedQueryables ) {
|
for ( Queryable persister : affectedQueryables ) {
|
||||||
spacesList.addAll( Arrays.asList( (String[]) persister.getQuerySpaces() ) );
|
spacesList.addAll( Arrays.asList( (String[]) persister.getQuerySpaces() ) );
|
||||||
|
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
entityCleanups.add( new EntityCleanup( persister.getCacheAccessStrategy() ) );
|
entityCleanups.add( new EntityCleanup( persister.getCacheAccessStrategy() ) );
|
||||||
}
|
}
|
||||||
if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
|
if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
|
||||||
|
@ -105,7 +105,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
||||||
if ( affectedEntity( tableSpaces, entitySpaces ) ) {
|
if ( affectedEntity( tableSpaces, entitySpaces ) ) {
|
||||||
spacesList.addAll( Arrays.asList( entitySpaces ) );
|
spacesList.addAll( Arrays.asList( entitySpaces ) );
|
||||||
|
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
entityCleanups.add( new EntityCleanup( persister.getCacheAccessStrategy() ) );
|
entityCleanups.add( new EntityCleanup( persister.getCacheAccessStrategy() ) );
|
||||||
}
|
}
|
||||||
if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
|
if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
|
||||||
|
|
|
@ -78,7 +78,7 @@ public abstract class EntityAction
|
||||||
protected abstract boolean hasPostCommitEventListeners();
|
protected abstract boolean hasPostCommitEventListeners();
|
||||||
|
|
||||||
protected boolean needsAfterTransactionCompletion() {
|
protected boolean needsAfterTransactionCompletion() {
|
||||||
return persister.hasCache() || hasPostCommitEventListeners();
|
return persister.canWriteToCache() || hasPostCommitEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object ck;
|
final Object ck;
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||||
ck = cache.generateCacheKey( id, persister, session.getFactory(), session.getTenantIdentifier() );
|
ck = cache.generateCacheKey( id, persister, session.getFactory(), session.getTenantIdentifier() );
|
||||||
lock = cache.lockItem( session, ck, version );
|
lock = cache.lockItem( session, ck, version );
|
||||||
|
@ -113,7 +113,7 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
persistenceContext.removeEntity( entry.getEntityKey() );
|
persistenceContext.removeEntity( entry.getEntityKey() );
|
||||||
persistenceContext.removeProxy( entry.getEntityKey() );
|
persistenceContext.removeProxy( entry.getEntityKey() );
|
||||||
|
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
persister.getCacheAccessStrategy().remove( session, ck);
|
persister.getCacheAccessStrategy().remove( session, ck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ public class EntityDeleteAction extends EntityAction {
|
||||||
@Override
|
@Override
|
||||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
|
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
|
||||||
EntityPersister entityPersister = getPersister();
|
EntityPersister entityPersister = getPersister();
|
||||||
if ( entityPersister.hasCache() ) {
|
if ( entityPersister.canWriteToCache() ) {
|
||||||
EntityRegionAccessStrategy cache = entityPersister.getCacheAccessStrategy();
|
EntityRegionAccessStrategy cache = entityPersister.getCacheAccessStrategy();
|
||||||
final Object ck = cache.generateCacheKey(
|
final Object ck = cache.generateCacheKey(
|
||||||
getId(),
|
getId(),
|
||||||
|
|
|
@ -249,7 +249,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCachePutEnabled(EntityPersister persister, SharedSessionContractImplementor session) {
|
private boolean isCachePutEnabled(EntityPersister persister, SharedSessionContractImplementor session) {
|
||||||
return persister.hasCache()
|
return persister.canWriteToCache()
|
||||||
&& !persister.isCacheInvalidationRequired()
|
&& !persister.isCacheInvalidationRequired()
|
||||||
&& session.getCacheMode().isPutEnabled();
|
&& session.getCacheMode().isPutEnabled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ public final class EntityUpdateAction extends EntityAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object ck;
|
final Object ck;
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||||
ck = cache.generateCacheKey(
|
ck = cache.generateCacheKey(
|
||||||
id,
|
id,
|
||||||
|
@ -184,7 +184,7 @@ public final class EntityUpdateAction extends EntityAction {
|
||||||
entry.postUpdate( instance, state, nextVersion );
|
entry.postUpdate( instance, state, nextVersion );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
if ( persister.isCacheInvalidationRequired() || entry.getStatus()!= Status.MANAGED ) {
|
if ( persister.isCacheInvalidationRequired() || entry.getStatus()!= Status.MANAGED ) {
|
||||||
persister.getCacheAccessStrategy().remove( session, ck);
|
persister.getCacheAccessStrategy().remove( session, ck);
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ public final class EntityUpdateAction extends EntityAction {
|
||||||
@Override
|
@Override
|
||||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws CacheException {
|
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws CacheException {
|
||||||
final EntityPersister persister = getPersister();
|
final EntityPersister persister = getPersister();
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||||
final Object ck = cache.generateCacheKey(
|
final Object ck = cache.generateCacheKey(
|
||||||
getId(),
|
getId(),
|
||||||
|
|
|
@ -2146,6 +2146,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
||||||
"Cache override referenced a non-root entity : " + cacheRegionDefinition.getRole()
|
"Cache override referenced a non-root entity : " + cacheRegionDefinition.getRole()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
entityBinding.setCached( true );
|
||||||
( (RootClass) entityBinding ).setCacheRegionName( cacheRegionDefinition.getRegion() );
|
( (RootClass) entityBinding ).setCacheRegionName( cacheRegionDefinition.getRegion() );
|
||||||
( (RootClass) entityBinding ).setCacheConcurrencyStrategy( cacheRegionDefinition.getUsage() );
|
( (RootClass) entityBinding ).setCacheConcurrencyStrategy( cacheRegionDefinition.getUsage() );
|
||||||
( (RootClass) entityBinding ).setLazyPropertiesCacheable( cacheRegionDefinition.isCacheLazy() );
|
( (RootClass) entityBinding ).setLazyPropertiesCacheable( cacheRegionDefinition.isCacheLazy() );
|
||||||
|
|
|
@ -331,7 +331,7 @@ public class ModelBinder {
|
||||||
}
|
}
|
||||||
rootEntityDescriptor.setCacheRegionName( caching.getRegion() );
|
rootEntityDescriptor.setCacheRegionName( caching.getRegion() );
|
||||||
rootEntityDescriptor.setLazyPropertiesCacheable( caching.isCacheLazyProperties() );
|
rootEntityDescriptor.setLazyPropertiesCacheable( caching.isCacheLazyProperties() );
|
||||||
rootEntityDescriptor.setCachingExplicitlyRequested( caching.getRequested() != TruthValue.UNKNOWN );
|
rootEntityDescriptor.setCached( caching.getRequested() != TruthValue.UNKNOWN );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindEntityIdentifier(
|
private void bindEntityIdentifier(
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.cfg;
|
package org.hibernate.cfg;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -21,7 +20,6 @@ import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
||||||
import javax.persistence.Cacheable;
|
|
||||||
import javax.persistence.CollectionTable;
|
import javax.persistence.CollectionTable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
|
@ -78,7 +76,6 @@ import org.hibernate.FetchMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.annotations.BatchSize;
|
import org.hibernate.annotations.BatchSize;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|
||||||
import org.hibernate.annotations.Cascade;
|
import org.hibernate.annotations.Cascade;
|
||||||
import org.hibernate.annotations.CascadeType;
|
import org.hibernate.annotations.CascadeType;
|
||||||
import org.hibernate.annotations.Check;
|
import org.hibernate.annotations.Check;
|
||||||
|
@ -105,7 +102,6 @@ import org.hibernate.annotations.ListIndexBase;
|
||||||
import org.hibernate.annotations.ManyToAny;
|
import org.hibernate.annotations.ManyToAny;
|
||||||
import org.hibernate.annotations.MapKeyType;
|
import org.hibernate.annotations.MapKeyType;
|
||||||
import org.hibernate.annotations.NaturalId;
|
import org.hibernate.annotations.NaturalId;
|
||||||
import org.hibernate.annotations.NaturalIdCache;
|
|
||||||
import org.hibernate.annotations.NotFound;
|
import org.hibernate.annotations.NotFound;
|
||||||
import org.hibernate.annotations.NotFoundAction;
|
import org.hibernate.annotations.NotFoundAction;
|
||||||
import org.hibernate.annotations.OnDelete;
|
import org.hibernate.annotations.OnDelete;
|
||||||
|
@ -625,8 +621,7 @@ public final class AnnotationBinder {
|
||||||
entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
|
entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
|
||||||
entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
|
entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
|
||||||
entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
|
entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
|
||||||
entityBinder.setCache( determineCacheSettings( clazzToProcess, context ) );
|
applyCacheSettings( entityBinder, clazzToProcess, context );
|
||||||
entityBinder.setNaturalIdCache( clazzToProcess, clazzToProcess.getAnnotation( NaturalIdCache.class ) );
|
|
||||||
|
|
||||||
bindFilters( clazzToProcess, entityBinder, context );
|
bindFilters( clazzToProcess, entityBinder, context );
|
||||||
|
|
||||||
|
@ -1158,80 +1153,19 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cache determineCacheSettings(XClass clazzToProcess, MetadataBuildingContext context) {
|
private static void applyCacheSettings(EntityBinder binder, XClass clazzToProcess, MetadataBuildingContext context) {
|
||||||
Cache cacheAnn = clazzToProcess.getAnnotation( Cache.class );
|
binder.applyCaching(
|
||||||
if ( cacheAnn != null ) {
|
clazzToProcess,
|
||||||
return cacheAnn;
|
determineSharedCacheMode( context ),
|
||||||
}
|
context
|
||||||
|
|
||||||
Cacheable cacheableAnn = clazzToProcess.getAnnotation( Cacheable.class );
|
);
|
||||||
SharedCacheMode mode = determineSharedCacheMode( context );
|
|
||||||
switch ( mode ) {
|
|
||||||
case ALL: {
|
|
||||||
cacheAnn = buildCacheMock( clazzToProcess.getName(), context );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ENABLE_SELECTIVE: {
|
|
||||||
if ( cacheableAnn != null && cacheableAnn.value() ) {
|
|
||||||
cacheAnn = buildCacheMock( clazzToProcess.getName(), context );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DISABLE_SELECTIVE: {
|
|
||||||
if ( cacheableAnn == null || cacheableAnn.value() ) {
|
|
||||||
cacheAnn = buildCacheMock( clazzToProcess.getName(), context );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// treat both NONE and UNSPECIFIED the same
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cacheAnn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SharedCacheMode determineSharedCacheMode(MetadataBuildingContext context) {
|
private static SharedCacheMode determineSharedCacheMode(MetadataBuildingContext context) {
|
||||||
return context.getBuildingOptions().getSharedCacheMode();
|
return context.getBuildingOptions().getSharedCacheMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cache buildCacheMock(String region, MetadataBuildingContext context) {
|
|
||||||
return new LocalCacheAnnotationImpl( region, determineCacheConcurrencyStrategy( context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CacheConcurrencyStrategy determineCacheConcurrencyStrategy(MetadataBuildingContext context) {
|
|
||||||
return CacheConcurrencyStrategy.fromAccessType(
|
|
||||||
context.getBuildingOptions().getImplicitCacheAccessType()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "ClassExplicitlyAnnotation" })
|
|
||||||
private static class LocalCacheAnnotationImpl implements Cache {
|
|
||||||
private final String region;
|
|
||||||
private final CacheConcurrencyStrategy usage;
|
|
||||||
|
|
||||||
private LocalCacheAnnotationImpl(String region, CacheConcurrencyStrategy usage) {
|
|
||||||
this.region = region;
|
|
||||||
this.usage = usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CacheConcurrencyStrategy usage() {
|
|
||||||
return usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String region() {
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String include() {
|
|
||||||
return "all";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<? extends Annotation> annotationType() {
|
|
||||||
return Cache.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PersistentClass makePersistentClass(
|
private static PersistentClass makePersistentClass(
|
||||||
InheritanceState inheritanceState,
|
InheritanceState inheritanceState,
|
||||||
PersistentClass superEntity,
|
PersistentClass superEntity,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.cfg.annotations;
|
package org.hibernate.cfg.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -15,7 +16,6 @@ import javax.persistence.Access;
|
||||||
import javax.persistence.Cacheable;
|
import javax.persistence.Cacheable;
|
||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.InheritanceType;
|
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.NamedEntityGraph;
|
import javax.persistence.NamedEntityGraph;
|
||||||
|
@ -23,6 +23,7 @@ import javax.persistence.NamedEntityGraphs;
|
||||||
import javax.persistence.PrimaryKeyJoinColumn;
|
import javax.persistence.PrimaryKeyJoinColumn;
|
||||||
import javax.persistence.SecondaryTable;
|
import javax.persistence.SecondaryTable;
|
||||||
import javax.persistence.SecondaryTables;
|
import javax.persistence.SecondaryTables;
|
||||||
|
import javax.persistence.SharedCacheMode;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
|
@ -127,17 +128,19 @@ public class EntityBinder {
|
||||||
// atm we use both from here; HBM binding solely uses InFlightMetadataCollector.EntityTableXref
|
// atm we use both from here; HBM binding solely uses InFlightMetadataCollector.EntityTableXref
|
||||||
private java.util.Map<String, Join> secondaryTables = new HashMap<String, Join>();
|
private java.util.Map<String, Join> secondaryTables = new HashMap<String, Join>();
|
||||||
private java.util.Map<String, Object> secondaryTableJoins = new HashMap<String, Object>();
|
private java.util.Map<String, Object> secondaryTableJoins = new HashMap<String, Object>();
|
||||||
private String cacheConcurrentStrategy;
|
|
||||||
private String cacheRegion;
|
|
||||||
private String naturalIdCacheRegion;
|
|
||||||
private List<Filter> filters = new ArrayList<Filter>();
|
private List<Filter> filters = new ArrayList<Filter>();
|
||||||
private InheritanceState inheritanceState;
|
private InheritanceState inheritanceState;
|
||||||
private boolean ignoreIdAnnotations;
|
private boolean ignoreIdAnnotations;
|
||||||
private boolean cacheLazyProperty;
|
|
||||||
private AccessType propertyAccessType = AccessType.DEFAULT;
|
private AccessType propertyAccessType = AccessType.DEFAULT;
|
||||||
private boolean wrapIdsInEmbeddedComponents;
|
private boolean wrapIdsInEmbeddedComponents;
|
||||||
private String subselect;
|
private String subselect;
|
||||||
|
|
||||||
|
private boolean isCached;
|
||||||
|
private String cacheConcurrentStrategy;
|
||||||
|
private String cacheRegion;
|
||||||
|
private boolean cacheLazyProperty;
|
||||||
|
private String naturalIdCacheRegion;
|
||||||
|
|
||||||
public boolean wrapIdsInEmbeddedComponents() {
|
public boolean wrapIdsInEmbeddedComponents() {
|
||||||
return wrapIdsInEmbeddedComponents;
|
return wrapIdsInEmbeddedComponents;
|
||||||
}
|
}
|
||||||
|
@ -281,17 +284,25 @@ public class EntityBinder {
|
||||||
}
|
}
|
||||||
rootClass.setMutable( mutable );
|
rootClass.setMutable( mutable );
|
||||||
rootClass.setExplicitPolymorphism( isExplicitPolymorphism( polymorphismType ) );
|
rootClass.setExplicitPolymorphism( isExplicitPolymorphism( polymorphismType ) );
|
||||||
if ( StringHelper.isNotEmpty( where ) ) rootClass.setWhere( where );
|
|
||||||
|
if ( StringHelper.isNotEmpty( where ) ) {
|
||||||
|
rootClass.setWhere( where );
|
||||||
|
}
|
||||||
|
|
||||||
if ( cacheConcurrentStrategy != null ) {
|
if ( cacheConcurrentStrategy != null ) {
|
||||||
rootClass.setCacheConcurrencyStrategy( cacheConcurrentStrategy );
|
rootClass.setCacheConcurrencyStrategy( cacheConcurrentStrategy );
|
||||||
rootClass.setCacheRegionName( cacheRegion );
|
rootClass.setCacheRegionName( cacheRegion );
|
||||||
rootClass.setLazyPropertiesCacheable( cacheLazyProperty );
|
rootClass.setLazyPropertiesCacheable( cacheLazyProperty );
|
||||||
}
|
}
|
||||||
|
|
||||||
rootClass.setNaturalIdCacheRegionName( naturalIdCacheRegion );
|
rootClass.setNaturalIdCacheRegionName( naturalIdCacheRegion );
|
||||||
|
|
||||||
boolean forceDiscriminatorInSelects = forceDiscriminator == null
|
boolean forceDiscriminatorInSelects = forceDiscriminator == null
|
||||||
? context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect()
|
? context.getBuildingOptions().shouldImplicitlyForceDiscriminatorInSelect()
|
||||||
: forceDiscriminator;
|
: forceDiscriminator;
|
||||||
|
|
||||||
rootClass.setForceDiscriminator( forceDiscriminatorInSelects );
|
rootClass.setForceDiscriminator( forceDiscriminatorInSelects );
|
||||||
|
|
||||||
if ( insertableDiscriminator != null ) {
|
if ( insertableDiscriminator != null ) {
|
||||||
rootClass.setDiscriminatorInsertable( insertableDiscriminator );
|
rootClass.setDiscriminatorInsertable( insertableDiscriminator );
|
||||||
}
|
}
|
||||||
|
@ -303,11 +314,10 @@ public class EntityBinder {
|
||||||
if (annotatedClass.isAnnotationPresent(Immutable.class)) {
|
if (annotatedClass.isAnnotationPresent(Immutable.class)) {
|
||||||
LOG.immutableAnnotationOnNonRoot(annotatedClass.getName());
|
LOG.immutableAnnotationOnNonRoot(annotatedClass.getName());
|
||||||
}
|
}
|
||||||
if ( annotatedClass.isAnnotationPresent( Cacheable.class ) ||
|
|
||||||
annotatedClass.isAnnotationPresent( Cache.class ) ) {
|
|
||||||
LOG.cacheOrCacheableAnnotationOnNonRoot( annotatedClass.getName() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
persistentClass.setCached( isCached );
|
||||||
|
|
||||||
persistentClass.setOptimisticLockStyle( getVersioning( optimisticLockType ) );
|
persistentClass.setOptimisticLockStyle( getVersioning( optimisticLockType ) );
|
||||||
persistentClass.setSelectBeforeUpdate( selectBeforeUpdate );
|
persistentClass.setSelectBeforeUpdate( selectBeforeUpdate );
|
||||||
|
|
||||||
|
@ -542,6 +552,164 @@ public class EntityBinder {
|
||||||
this.wrapIdsInEmbeddedComponents = wrapIdsInEmbeddedComponents;
|
this.wrapIdsInEmbeddedComponents = wrapIdsInEmbeddedComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void applyCaching(
|
||||||
|
XClass clazzToProcess,
|
||||||
|
SharedCacheMode sharedCacheMode,
|
||||||
|
MetadataBuildingContext context) {
|
||||||
|
final Cache explicitCacheAnn = clazzToProcess.getAnnotation( Cache.class );
|
||||||
|
final Cacheable explicitCacheableAnn = clazzToProcess.getAnnotation( Cacheable.class );
|
||||||
|
|
||||||
|
isCached = false;
|
||||||
|
cacheConcurrentStrategy = null;
|
||||||
|
cacheRegion = null;
|
||||||
|
cacheLazyProperty = true;
|
||||||
|
|
||||||
|
if ( persistentClass instanceof RootClass ) {
|
||||||
|
Cache effectiveCacheAnn = explicitCacheAnn;
|
||||||
|
|
||||||
|
if ( explicitCacheAnn != null ) {
|
||||||
|
// preserve legacy behavior of circumventing SharedCacheMode when Hibernate's @Cache is used.
|
||||||
|
isCached = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
effectiveCacheAnn = buildCacheMock( clazzToProcess.getName(), context );
|
||||||
|
|
||||||
|
switch ( sharedCacheMode ) {
|
||||||
|
case ALL: {
|
||||||
|
// all entities should be cached
|
||||||
|
isCached = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ENABLE_SELECTIVE: {
|
||||||
|
if ( explicitCacheableAnn != null && explicitCacheableAnn.value() ) {
|
||||||
|
isCached = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DISABLE_SELECTIVE: {
|
||||||
|
if ( explicitCacheableAnn == null || explicitCacheableAnn.value() ) {
|
||||||
|
isCached = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// treat both NONE and UNSPECIFIED the same
|
||||||
|
isCached = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheConcurrentStrategy = effectiveCacheAnn.usage().name();
|
||||||
|
cacheRegion = effectiveCacheAnn.region();
|
||||||
|
switch ( effectiveCacheAnn.include().toLowerCase( Locale.ROOT ) ) {
|
||||||
|
case "all": {
|
||||||
|
cacheLazyProperty = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "non-lazy": {
|
||||||
|
cacheLazyProperty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new AnnotationException(
|
||||||
|
"Unknown @Cache.include value [" + effectiveCacheAnn.include() + "] : "
|
||||||
|
+ annotatedClass.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( explicitCacheAnn != null ) {
|
||||||
|
LOG.cacheOrCacheableAnnotationOnNonRoot( persistentClass.getClassName() );
|
||||||
|
}
|
||||||
|
else if ( explicitCacheableAnn == null && persistentClass.getSuperclass() != null ) {
|
||||||
|
// we should inherit our super's caching config
|
||||||
|
isCached = persistentClass.getSuperclass().isCached();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ( sharedCacheMode ) {
|
||||||
|
case ALL: {
|
||||||
|
// all entities should be cached
|
||||||
|
isCached = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ENABLE_SELECTIVE: {
|
||||||
|
// only entities with @Cacheable(true) should be cached
|
||||||
|
if ( explicitCacheableAnn != null && explicitCacheableAnn.value() ) {
|
||||||
|
isCached = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DISABLE_SELECTIVE: {
|
||||||
|
if ( explicitCacheableAnn == null || !explicitCacheableAnn.value() ) {
|
||||||
|
isCached = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// treat both NONE and UNSPECIFIED the same
|
||||||
|
isCached = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
naturalIdCacheRegion = null;
|
||||||
|
|
||||||
|
final NaturalIdCache naturalIdCacheAnn = clazzToProcess.getAnnotation( NaturalIdCache.class );
|
||||||
|
if ( naturalIdCacheAnn != null ) {
|
||||||
|
if ( BinderHelper.isEmptyAnnotationValue( naturalIdCacheAnn.region() ) ) {
|
||||||
|
if ( explicitCacheAnn != null && StringHelper.isNotEmpty( explicitCacheAnn.region() ) ) {
|
||||||
|
naturalIdCacheRegion = explicitCacheAnn.region() + NATURAL_ID_CACHE_SUFFIX;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
naturalIdCacheRegion = clazzToProcess.getName() + NATURAL_ID_CACHE_SUFFIX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
naturalIdCacheRegion = naturalIdCacheAnn.region();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Cache buildCacheMock(String region, MetadataBuildingContext context) {
|
||||||
|
return new LocalCacheAnnotationStub( region, determineCacheConcurrencyStrategy( context ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "ClassExplicitlyAnnotation" })
|
||||||
|
private static class LocalCacheAnnotationStub implements Cache {
|
||||||
|
private final String region;
|
||||||
|
private final CacheConcurrencyStrategy usage;
|
||||||
|
|
||||||
|
private LocalCacheAnnotationStub(String region, CacheConcurrencyStrategy usage) {
|
||||||
|
this.region = region;
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheConcurrencyStrategy usage() {
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String region() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String include() {
|
||||||
|
return "all";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends Annotation> annotationType() {
|
||||||
|
return Cache.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CacheConcurrencyStrategy determineCacheConcurrencyStrategy(MetadataBuildingContext context) {
|
||||||
|
return CacheConcurrencyStrategy.fromAccessType(
|
||||||
|
context.getBuildingOptions().getImplicitCacheAccessType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private static class EntityTableObjectNameSource implements ObjectNameSource {
|
private static class EntityTableObjectNameSource implements ObjectNameSource {
|
||||||
private final String explicitName;
|
private final String explicitName;
|
||||||
|
@ -1044,48 +1212,6 @@ public class EntityBinder {
|
||||||
return secondaryTables;
|
return secondaryTables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCache(Cache cacheAnn) {
|
|
||||||
if ( cacheAnn != null ) {
|
|
||||||
cacheRegion = BinderHelper.isEmptyAnnotationValue( cacheAnn.region() ) ?
|
|
||||||
null :
|
|
||||||
cacheAnn.region();
|
|
||||||
cacheConcurrentStrategy = getCacheConcurrencyStrategy( cacheAnn.usage() );
|
|
||||||
if ( "all".equalsIgnoreCase( cacheAnn.include() ) ) {
|
|
||||||
cacheLazyProperty = true;
|
|
||||||
}
|
|
||||||
else if ( "non-lazy".equalsIgnoreCase( cacheAnn.include() ) ) {
|
|
||||||
cacheLazyProperty = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AnnotationException( "Unknown lazy property annotations: " + cacheAnn.include() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cacheConcurrentStrategy = null;
|
|
||||||
cacheRegion = null;
|
|
||||||
cacheLazyProperty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNaturalIdCache(XClass clazzToProcess, NaturalIdCache naturalIdCacheAnn) {
|
|
||||||
if ( naturalIdCacheAnn != null ) {
|
|
||||||
if ( BinderHelper.isEmptyAnnotationValue( naturalIdCacheAnn.region() ) ) {
|
|
||||||
if (cacheRegion != null) {
|
|
||||||
naturalIdCacheRegion = cacheRegion + NATURAL_ID_CACHE_SUFFIX;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
naturalIdCacheRegion = clazzToProcess.getName() + NATURAL_ID_CACHE_SUFFIX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
naturalIdCacheRegion = naturalIdCacheAnn.region();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
naturalIdCacheRegion = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getCacheConcurrencyStrategy(CacheConcurrencyStrategy strategy) {
|
public static String getCacheConcurrencyStrategy(CacheConcurrencyStrategy strategy) {
|
||||||
org.hibernate.cache.spi.access.AccessType accessType = strategy.toAccessType();
|
org.hibernate.cache.spi.access.AccessType accessType = strategy.toAccessType();
|
||||||
return accessType == null ? null : accessType.getExternalName();
|
return accessType == null ? null : accessType.getExternalName();
|
||||||
|
|
|
@ -1670,7 +1670,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
@Override
|
@Override
|
||||||
public void registerInsertedKey(EntityPersister persister, Serializable id) {
|
public void registerInsertedKey(EntityPersister persister, Serializable id) {
|
||||||
// we only are worried about registering these if the persister defines caching
|
// we only are worried about registering these if the persister defines caching
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
if ( insertedKeysMap == null ) {
|
if ( insertedKeysMap == null ) {
|
||||||
insertedKeysMap = new HashMap<>();
|
insertedKeysMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
@ -1687,7 +1687,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
@Override
|
@Override
|
||||||
public boolean wasInsertedDuringTransaction(EntityPersister persister, Serializable id) {
|
public boolean wasInsertedDuringTransaction(EntityPersister persister, Serializable id) {
|
||||||
// again, we only really care if the entity is cached
|
// again, we only really care if the entity is cached
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
if ( insertedKeysMap != null ) {
|
if ( insertedKeysMap != null ) {
|
||||||
final List<Serializable> insertedEntityIds = insertedKeysMap.get( persister.getRootEntityName() );
|
final List<Serializable> insertedEntityIds = insertedKeysMap.get( persister.getRootEntityName() );
|
||||||
if ( insertedEntityIds != null ) {
|
if ( insertedEntityIds != null ) {
|
||||||
|
|
|
@ -183,7 +183,7 @@ public final class TwoPhaseLoad {
|
||||||
persister.setPropertyValues( entity, hydratedState );
|
persister.setPropertyValues( entity, hydratedState );
|
||||||
|
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
final SessionFactoryImplementor factory = session.getFactory();
|
||||||
if ( persister.hasCache() && session.getCacheMode().isPutEnabled() ) {
|
if ( persister.canWriteToCache() && session.getCacheMode().isPutEnabled() ) {
|
||||||
|
|
||||||
if ( debugEnabled ) {
|
if ( debugEnabled ) {
|
||||||
LOG.debugf(
|
LOG.debugf(
|
||||||
|
|
|
@ -215,7 +215,7 @@ public class BatchFetchQueue {
|
||||||
|
|
||||||
private boolean isCached(EntityKey entityKey, EntityPersister persister) {
|
private boolean isCached(EntityKey entityKey, EntityPersister persister) {
|
||||||
final SharedSessionContractImplementor session = context.getSession();
|
final SharedSessionContractImplementor session = context.getSession();
|
||||||
if ( context.getSession().getCacheMode().isGetEnabled() && persister.hasCache() ) {
|
if ( context.getSession().getCacheMode().isGetEnabled() && persister.canReadFromCache() ) {
|
||||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||||
final Object key = cache.generateCacheKey(
|
final Object key = cache.generateCacheKey(
|
||||||
entityKey.getIdentifier(),
|
entityKey.getIdentifier(),
|
||||||
|
|
|
@ -61,7 +61,7 @@ public abstract class AbstractLockUpgradeEventListener extends AbstractReassocia
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean cachingEnabled = persister.hasCache();
|
final boolean cachingEnabled = persister.canWriteToCache();
|
||||||
SoftLock lock = null;
|
SoftLock lock = null;
|
||||||
Object ck = null;
|
Object ck = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -385,7 +385,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
||||||
SoftLock lock = null;
|
SoftLock lock = null;
|
||||||
final Object ck;
|
final Object ck;
|
||||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
ck = cache.generateCacheKey(
|
ck = cache.generateCacheKey(
|
||||||
event.getEntityId(),
|
event.getEntityId(),
|
||||||
persister,
|
persister,
|
||||||
|
@ -403,7 +403,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
||||||
entity = load( event, persister, keyToLoad, options );
|
entity = load( event, persister, keyToLoad, options );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
cache.unlockItem( source, ck, lock );
|
cache.unlockItem( source, ck, lock );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,7 +583,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
||||||
final EntityKey entityKey) {
|
final EntityKey entityKey) {
|
||||||
|
|
||||||
final SessionImplementor source = event.getSession();
|
final SessionImplementor source = event.getSession();
|
||||||
final boolean useCache = persister.hasCache()
|
final boolean useCache = persister.canReadFromCache()
|
||||||
&& source.getCacheMode().isGetEnabled()
|
&& source.getCacheMode().isGetEnabled()
|
||||||
&& event.getLockMode().lessThan( LockMode.READ );
|
&& event.getLockMode().lessThan( LockMode.READ );
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
Object previousVersion = null;
|
Object previousVersion = null;
|
||||||
if ( persister.isVersionPropertyGenerated() ) {
|
if ( persister.isVersionPropertyGenerated() ) {
|
||||||
// we need to grab the version value from the entity, otherwise
|
// we need to grab the version value from the entity, otherwise
|
||||||
|
|
|
@ -629,15 +629,6 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
|
||||||
this.withClauseFragment = withClauseFragment;
|
this.withClauseFragment = withClauseFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasCacheablePersister() {
|
|
||||||
if ( getQueryableCollection() != null ) {
|
|
||||||
return getQueryableCollection().hasCache();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return getQueryable().hasCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handlePropertyBeingDereferenced(Type propertySource, String propertyName) {
|
public void handlePropertyBeingDereferenced(Type propertySource, String propertyName) {
|
||||||
if ( getQueryableCollection() != null && CollectionProperties.isCollectionProperty( propertyName ) ) {
|
if ( getQueryableCollection() != null && CollectionProperties.isCollectionProperty( propertyName ) ) {
|
||||||
// propertyName refers to something like collection.size...
|
// propertyName refers to something like collection.size...
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
|
@ -119,7 +120,7 @@ public class CacheImpl implements CacheImplementor {
|
||||||
@Override
|
@Override
|
||||||
public boolean containsEntity(String entityName, Serializable identifier) {
|
public boolean containsEntity(String entityName, Serializable identifier) {
|
||||||
EntityPersister p = sessionFactory.getMetamodel().entityPersister( entityName );
|
EntityPersister p = sessionFactory.getMetamodel().entityPersister( entityName );
|
||||||
if ( p.hasCache() ) {
|
if ( p.canReadFromCache() ) {
|
||||||
EntityRegionAccessStrategy cache = p.getCacheAccessStrategy();
|
EntityRegionAccessStrategy cache = p.getCacheAccessStrategy();
|
||||||
Object key = cache.generateCacheKey( identifier, p, sessionFactory, null ); // have to assume non tenancy
|
Object key = cache.generateCacheKey( identifier, p, sessionFactory, null ); // have to assume non tenancy
|
||||||
return cache.getRegion().contains( key );
|
return cache.getRegion().contains( key );
|
||||||
|
@ -137,7 +138,7 @@ public class CacheImpl implements CacheImplementor {
|
||||||
@Override
|
@Override
|
||||||
public void evictEntity(String entityName, Serializable identifier) {
|
public void evictEntity(String entityName, Serializable identifier) {
|
||||||
EntityPersister p = sessionFactory.getMetamodel().entityPersister( entityName );
|
EntityPersister p = sessionFactory.getMetamodel().entityPersister( entityName );
|
||||||
if ( p.hasCache() ) {
|
if ( p.canWriteToCache() ) {
|
||||||
if ( LOG.isDebugEnabled() ) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
LOG.debugf(
|
LOG.debugf(
|
||||||
"Evicting second-level cache: %s",
|
"Evicting second-level cache: %s",
|
||||||
|
@ -158,7 +159,7 @@ public class CacheImpl implements CacheImplementor {
|
||||||
@Override
|
@Override
|
||||||
public void evictEntityRegion(String entityName) {
|
public void evictEntityRegion(String entityName) {
|
||||||
EntityPersister p = sessionFactory.getMetamodel().entityPersister( entityName );
|
EntityPersister p = sessionFactory.getMetamodel().entityPersister( entityName );
|
||||||
if ( p.hasCache() ) {
|
if ( p.canWriteToCache() ) {
|
||||||
if ( LOG.isDebugEnabled() ) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
LOG.debugf( "Evicting second-level cache: %s", p.getEntityName() );
|
LOG.debugf( "Evicting second-level cache: %s", p.getEntityName() );
|
||||||
}
|
}
|
||||||
|
@ -428,12 +429,23 @@ public class CacheImpl implements CacheImplementor {
|
||||||
throw new PersistenceException( "Hibernate cannot unwrap Cache as " + cls.getName() );
|
throw new PersistenceException( "Hibernate cannot unwrap Cache as " + cls.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo (5.3) : normalize caching to the "first subclass" in the hierarchy whose subclasses all define caching
|
||||||
|
// 5.3 adds support for "subclass only" caching, so we need a different paradigm for
|
||||||
|
// code such as this that assumes root-only caching
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityRegionAccessStrategy determineEntityRegionAccessStrategy(PersistentClass model) {
|
public EntityRegionAccessStrategy determineEntityRegionAccessStrategy(PersistentClass model) {
|
||||||
final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();
|
if ( ! settings.isSecondLevelCacheEnabled() ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache settings are defined on root entity
|
||||||
|
final RootClass rootEntity = model.getRootClass();
|
||||||
|
|
||||||
|
final String cacheRegionName = cacheRegionPrefix + rootEntity.getCacheRegionName();
|
||||||
EntityRegionAccessStrategy accessStrategy = entityRegionAccessStrategyMap.get( cacheRegionName );
|
EntityRegionAccessStrategy accessStrategy = entityRegionAccessStrategyMap.get( cacheRegionName );
|
||||||
if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
|
if ( accessStrategy == null ) {
|
||||||
final AccessType accessType = AccessType.fromExternalName( model.getCacheConcurrencyStrategy() );
|
final AccessType accessType = AccessType.fromExternalName( rootEntity.getCacheConcurrencyStrategy() );
|
||||||
if ( accessType != null ) {
|
if ( accessType != null ) {
|
||||||
LOG.tracef( "Building shared cache region for entity data [%s]", model.getEntityName() );
|
LOG.tracef( "Building shared cache region for entity data [%s]", model.getEntityName() );
|
||||||
EntityRegion entityRegion = regionFactory.buildEntityRegion(
|
EntityRegion entityRegion = regionFactory.buildEntityRegion(
|
||||||
|
|
|
@ -1768,7 +1768,7 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
void unknownJavaTypeNoEqualsHashCode(Class javaType);
|
void unknownJavaTypeNoEqualsHashCode(Class javaType);
|
||||||
|
|
||||||
@LogMessage(level = WARN)
|
@LogMessage(level = WARN)
|
||||||
@Message(value = "@javax.persistence.Cacheable or @org.hibernate.annotations.Cache used on a non-root entity: ignored for %s", id = 482)
|
@Message(value = "@org.hibernate.annotations.Cache used on a non-root entity: ignored for %s", id = 482)
|
||||||
void cacheOrCacheableAnnotationOnNonRoot(String className);
|
void cacheOrCacheableAnnotationOnNonRoot(String className);
|
||||||
|
|
||||||
@LogMessage(level = WARN)
|
@LogMessage(level = WARN)
|
||||||
|
|
|
@ -219,7 +219,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if ( persister.hasCache() ) {
|
if ( persister.canWriteToCache() ) {
|
||||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||||
final Object ck = cache.generateCacheKey( id, persister, getFactory(), getTenantIdentifier() );
|
final Object ck = cache.generateCacheKey( id, persister, getFactory(), getTenantIdentifier() );
|
||||||
cache.evict( ck );
|
cache.evict( ck );
|
||||||
|
|
|
@ -90,6 +90,8 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
|
||||||
private Component declaredIdentifierMapper;
|
private Component declaredIdentifierMapper;
|
||||||
private OptimisticLockStyle optimisticLockStyle;
|
private OptimisticLockStyle optimisticLockStyle;
|
||||||
|
|
||||||
|
private boolean isCached;
|
||||||
|
|
||||||
public PersistentClass(MetadataBuildingContext metadataBuildingContext) {
|
public PersistentClass(MetadataBuildingContext metadataBuildingContext) {
|
||||||
this.metadataBuildingContext = metadataBuildingContext;
|
this.metadataBuildingContext = metadataBuildingContext;
|
||||||
}
|
}
|
||||||
|
@ -270,10 +272,35 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
|
||||||
|
|
||||||
public abstract boolean isVersioned();
|
public abstract boolean isVersioned();
|
||||||
|
|
||||||
public abstract String getNaturalIdCacheRegionName();
|
|
||||||
|
public boolean isCached() {
|
||||||
|
return isCached;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCached(boolean cached) {
|
||||||
|
isCached = cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use {@link #isCached} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public boolean isCachingExplicitlyRequested() {
|
||||||
|
return isCached();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use {@link #setCached} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void setCachingExplicitlyRequested(boolean cached) {
|
||||||
|
setCached( cached );
|
||||||
|
}
|
||||||
|
|
||||||
public abstract String getCacheConcurrencyStrategy();
|
public abstract String getCacheConcurrencyStrategy();
|
||||||
|
|
||||||
|
public abstract String getNaturalIdCacheRegionName();
|
||||||
|
|
||||||
public abstract PersistentClass getSuperclass();
|
public abstract PersistentClass getSuperclass();
|
||||||
|
|
||||||
public abstract boolean isExplicitPolymorphism();
|
public abstract boolean isExplicitPolymorphism();
|
||||||
|
@ -955,8 +982,6 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isLazyPropertiesCacheable();
|
|
||||||
|
|
||||||
// The following methods are added to support @MappedSuperclass in the metamodel
|
// The following methods are added to support @MappedSuperclass in the metamodel
|
||||||
public Iterator getDeclaredPropertyIterator() {
|
public Iterator getDeclaredPropertyIterator() {
|
||||||
ArrayList iterators = new ArrayList();
|
ArrayList iterators = new ArrayList();
|
||||||
|
|
|
@ -34,10 +34,12 @@ public class RootClass extends PersistentClass implements TableOwner {
|
||||||
private KeyValue identifier;
|
private KeyValue identifier;
|
||||||
private Property version;
|
private Property version;
|
||||||
private boolean polymorphic;
|
private boolean polymorphic;
|
||||||
|
|
||||||
private String cacheConcurrencyStrategy;
|
private String cacheConcurrencyStrategy;
|
||||||
private String cacheRegionName;
|
private String cacheRegionName;
|
||||||
private String naturalIdCacheRegionName;
|
|
||||||
private boolean lazyPropertiesCacheable = true;
|
private boolean lazyPropertiesCacheable = true;
|
||||||
|
private String naturalIdCacheRegionName;
|
||||||
|
|
||||||
private Value discriminator;
|
private Value discriminator;
|
||||||
private boolean mutable = true;
|
private boolean mutable = true;
|
||||||
private boolean embeddedIdentifier;
|
private boolean embeddedIdentifier;
|
||||||
|
@ -50,7 +52,6 @@ public class RootClass extends PersistentClass implements TableOwner {
|
||||||
private int nextSubclassId;
|
private int nextSubclassId;
|
||||||
private Property declaredIdentifierProperty;
|
private Property declaredIdentifierProperty;
|
||||||
private Property declaredVersion;
|
private Property declaredVersion;
|
||||||
private boolean cachingExplicitlyRequested;
|
|
||||||
|
|
||||||
public RootClass(MetadataBuildingContext metadataBuildingContext) {
|
public RootClass(MetadataBuildingContext metadataBuildingContext) {
|
||||||
super( metadataBuildingContext );
|
super( metadataBuildingContext );
|
||||||
|
@ -314,6 +315,14 @@ public class RootClass extends PersistentClass implements TableOwner {
|
||||||
this.cacheRegionName = cacheRegionName;
|
this.cacheRegionName = cacheRegionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLazyPropertiesCacheable() {
|
||||||
|
return lazyPropertiesCacheable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLazyPropertiesCacheable(boolean lazyPropertiesCacheable) {
|
||||||
|
this.lazyPropertiesCacheable = lazyPropertiesCacheable;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNaturalIdCacheRegionName() {
|
public String getNaturalIdCacheRegionName() {
|
||||||
return naturalIdCacheRegionName;
|
return naturalIdCacheRegionName;
|
||||||
|
@ -323,15 +332,6 @@ public class RootClass extends PersistentClass implements TableOwner {
|
||||||
this.naturalIdCacheRegionName = naturalIdCacheRegionName;
|
this.naturalIdCacheRegionName = naturalIdCacheRegionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLazyPropertiesCacheable() {
|
|
||||||
return lazyPropertiesCacheable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLazyPropertiesCacheable(boolean lazyPropertiesCacheable) {
|
|
||||||
this.lazyPropertiesCacheable = lazyPropertiesCacheable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isJoinedSubclass() {
|
public boolean isJoinedSubclass() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -360,11 +360,4 @@ public class RootClass extends PersistentClass implements TableOwner {
|
||||||
return mv.accept( this );
|
return mv.accept( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCachingExplicitlyRequested(boolean explicitlyRequested) {
|
|
||||||
this.cachingExplicitlyRequested = explicitlyRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCachingExplicitlyRequested() {
|
|
||||||
return cachingExplicitlyRequested;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class Subclass extends PersistentClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCacheConcurrencyStrategy() {
|
public String getCacheConcurrencyStrategy() {
|
||||||
return getSuperclass().getCacheConcurrencyStrategy();
|
return getRootClass().getCacheConcurrencyStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RootClass getRootClass() {
|
public RootClass getRootClass() {
|
||||||
|
@ -190,10 +190,6 @@ public class Subclass extends PersistentClass {
|
||||||
this.classPersisterClass = classPersisterClass;
|
this.classPersisterClass = classPersisterClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLazyPropertiesCacheable() {
|
|
||||||
return getSuperclass().isLazyPropertiesCacheable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJoinClosureSpan() {
|
public int getJoinClosureSpan() {
|
||||||
return getSuperclass().getJoinClosureSpan() + super.getJoinClosureSpan();
|
return getSuperclass().getJoinClosureSpan() + super.getJoinClosureSpan();
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
|
import org.hibernate.mapping.Subclass;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.metadata.ClassMetadata;
|
import org.hibernate.metadata.ClassMetadata;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
@ -148,6 +149,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
private final SessionFactoryImplementor factory;
|
private final SessionFactoryImplementor factory;
|
||||||
|
private final boolean canReadFromCache;
|
||||||
|
private final boolean canWriteToCache;
|
||||||
private final EntityRegionAccessStrategy cacheAccessStrategy;
|
private final EntityRegionAccessStrategy cacheAccessStrategy;
|
||||||
private final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy;
|
private final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy;
|
||||||
private final boolean isLazyPropertiesCacheable;
|
private final boolean isLazyPropertiesCacheable;
|
||||||
|
@ -512,9 +515,21 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
this.factory = creationContext.getSessionFactory();
|
this.factory = creationContext.getSessionFactory();
|
||||||
|
|
||||||
|
if ( creationContext.getSessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled() ) {
|
||||||
|
this.canWriteToCache = persistentClass.isCached();
|
||||||
|
this.canReadFromCache = determineCanReadFromCache( persistentClass );
|
||||||
this.cacheAccessStrategy = cacheAccessStrategy;
|
this.cacheAccessStrategy = cacheAccessStrategy;
|
||||||
|
this.isLazyPropertiesCacheable = persistentClass.getRootClass().isLazyPropertiesCacheable();
|
||||||
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
|
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
|
||||||
isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable();
|
}
|
||||||
|
else {
|
||||||
|
this.canWriteToCache = false;
|
||||||
|
this.canReadFromCache = false;
|
||||||
|
this.cacheAccessStrategy = null;
|
||||||
|
this.isLazyPropertiesCacheable = true;
|
||||||
|
this.naturalIdRegionAccessStrategy = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.entityMetamodel = new EntityMetamodel( persistentClass, this, factory );
|
this.entityMetamodel = new EntityMetamodel( persistentClass, this, factory );
|
||||||
this.entityTuplizer = this.entityMetamodel.getTuplizer();
|
this.entityTuplizer = this.entityMetamodel.getTuplizer();
|
||||||
|
@ -830,6 +845,22 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private boolean determineCanReadFromCache(PersistentClass persistentClass) {
|
||||||
|
if ( persistentClass.isCached() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Iterator<Subclass> subclassIterator = persistentClass.getSubclassIterator();
|
||||||
|
while ( subclassIterator.hasNext() ) {
|
||||||
|
final Subclass subclass = subclassIterator.next();
|
||||||
|
if ( subclass.isCached() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected CacheEntryHelper buildCacheEntryHelper() {
|
protected CacheEntryHelper buildCacheEntryHelper() {
|
||||||
if ( cacheAccessStrategy == null ) {
|
if ( cacheAccessStrategy == null ) {
|
||||||
// the entity defined no caching...
|
// the entity defined no caching...
|
||||||
|
@ -985,7 +1016,7 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( session.getCacheMode().isGetEnabled() && hasCache() && isLazyPropertiesCacheable() ) {
|
if ( session.getCacheMode().isGetEnabled() && canReadFromCache() && isLazyPropertiesCacheable() ) {
|
||||||
final EntityRegionAccessStrategy cache = getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = getCacheAccessStrategy();
|
||||||
final Object cacheKey = cache.generateCacheKey(id, this, session.getFactory(), session.getTenantIdentifier() );
|
final Object cacheKey = cache.generateCacheKey(id, this, session.getFactory(), session.getTenantIdentifier() );
|
||||||
final Object ce = CacheHelper.fromSharedCache( session, cacheKey, cache );
|
final Object ce = CacheHelper.fromSharedCache( session, cacheKey, cache );
|
||||||
|
@ -4293,8 +4324,18 @@ public abstract class AbstractEntityPersister
|
||||||
return entityMetamodel;
|
return entityMetamodel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canReadFromCache() {
|
||||||
|
return canReadFromCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canWriteToCache() {
|
||||||
|
return canWriteToCache;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasCache() {
|
public boolean hasCache() {
|
||||||
return cacheAccessStrategy != null;
|
return canWriteToCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityRegionAccessStrategy getCacheAccessStrategy() {
|
public EntityRegionAccessStrategy getCacheAccessStrategy() {
|
||||||
|
@ -4467,7 +4508,7 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if it is in the second-level cache
|
// check to see if it is in the second-level cache
|
||||||
if ( session.getCacheMode().isGetEnabled() && hasCache() ) {
|
if ( session.getCacheMode().isGetEnabled() && canReadFromCache() ) {
|
||||||
final EntityRegionAccessStrategy cache = getCacheAccessStrategy();
|
final EntityRegionAccessStrategy cache = getCacheAccessStrategy();
|
||||||
final Object ck = cache.generateCacheKey( id, this, session.getFactory(), session.getTenantIdentifier() );
|
final Object ck = cache.generateCacheKey( id, this, session.getFactory(), session.getTenantIdentifier() );
|
||||||
final Object ce = CacheHelper.fromSharedCache( session, ck, getCacheAccessStrategy() );
|
final Object ce = CacheHelper.fromSharedCache( session, ck, getCacheAccessStrategy() );
|
||||||
|
|
|
@ -503,9 +503,16 @@ public interface EntityPersister extends OptimisticCacheSource, EntityDefinition
|
||||||
* Should lazy properties of this entity be cached?
|
* Should lazy properties of this entity be cached?
|
||||||
*/
|
*/
|
||||||
boolean isLazyPropertiesCacheable();
|
boolean isLazyPropertiesCacheable();
|
||||||
|
|
||||||
|
boolean canReadFromCache();
|
||||||
|
boolean canWriteToCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this class have a cache.
|
* Does this class have a cache.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #canReadFromCache()} and/or {@link #canWriteToCache()} depending on need
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
boolean hasCache();
|
boolean hasCache();
|
||||||
/**
|
/**
|
||||||
* Get the cache (optional operation)
|
* Get the cache (optional operation)
|
||||||
|
|
|
@ -13,7 +13,6 @@ import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.SharedCacheMode;
|
import javax.persistence.SharedCacheMode;
|
||||||
|
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.cache.internal.NoCachingRegionFactory;
|
|
||||||
import org.hibernate.cache.spi.access.AccessType;
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.jpa.AvailableSettings;
|
import org.hibernate.jpa.AvailableSettings;
|
||||||
|
@ -24,12 +23,11 @@ import org.hibernate.mapping.PersistentClass;
|
||||||
|
|
||||||
import org.hibernate.testing.cache.CachingRegionFactory;
|
import org.hibernate.testing.cache.CachingRegionFactory;
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this is hacky transient step until EMF building is integrated with metamodel
|
* this is hacky transient step until EMF building is integrated with metamodel
|
||||||
|
@ -51,13 +49,13 @@ public class ConfigurationTest extends BaseUnitTestCase {
|
||||||
MetadataImplementor metadata = buildMetadata( SharedCacheMode.NONE );
|
MetadataImplementor metadata = buildMetadata( SharedCacheMode.NONE );
|
||||||
|
|
||||||
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -65,13 +63,13 @@ public class ConfigurationTest extends BaseUnitTestCase {
|
||||||
MetadataImplementor metadata = buildMetadata( SharedCacheMode.UNSPECIFIED );
|
MetadataImplementor metadata = buildMetadata( SharedCacheMode.UNSPECIFIED );
|
||||||
|
|
||||||
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -79,13 +77,13 @@ public class ConfigurationTest extends BaseUnitTestCase {
|
||||||
MetadataImplementor metadata = buildMetadata( SharedCacheMode.ALL );
|
MetadataImplementor metadata = buildMetadata( SharedCacheMode.ALL );
|
||||||
|
|
||||||
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
||||||
assertNotNull( pc.getCacheConcurrencyStrategy() );
|
assertTrue( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
||||||
assertNotNull( pc.getCacheConcurrencyStrategy() );
|
assertTrue( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
||||||
assertNotNull( pc.getCacheConcurrencyStrategy() );
|
assertTrue( pc.isCached() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -93,13 +91,13 @@ public class ConfigurationTest extends BaseUnitTestCase {
|
||||||
MetadataImplementor metadata = buildMetadata( SharedCacheMode.ENABLE_SELECTIVE );
|
MetadataImplementor metadata = buildMetadata( SharedCacheMode.ENABLE_SELECTIVE );
|
||||||
|
|
||||||
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
||||||
assertNotNull( pc.getCacheConcurrencyStrategy() );
|
assertTrue( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -107,13 +105,13 @@ public class ConfigurationTest extends BaseUnitTestCase {
|
||||||
MetadataImplementor metadata = buildMetadata( SharedCacheMode.DISABLE_SELECTIVE );
|
MetadataImplementor metadata = buildMetadata( SharedCacheMode.DISABLE_SELECTIVE );
|
||||||
|
|
||||||
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
PersistentClass pc = metadata.getEntityBinding( ExplicitlyCacheableEntity.class.getName() );
|
||||||
assertNotNull( pc.getCacheConcurrencyStrategy() );
|
assertTrue( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
pc = metadata.getEntityBinding( ExplicitlyNonCacheableEntity.class.getName() );
|
||||||
assertNull( pc.getCacheConcurrencyStrategy() );
|
assertFalse( pc.isCached() );
|
||||||
|
|
||||||
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
pc = metadata.getEntityBinding( NoCacheableAnnotationEntity.class.getName() );
|
||||||
assertNotNull( pc.getCacheConcurrencyStrategy() );
|
assertTrue( pc.isCached() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
|
@ -411,6 +411,16 @@ public class PersisterClassProviderTest {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canReadFromCache() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canWriteToCache() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasCache() {
|
public boolean hasCache() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ public class NonRootEntityWithCacheAnnotationTest {
|
||||||
.buildMetadata();
|
.buildMetadata();
|
||||||
|
|
||||||
assertTrue( triggerable.wasTriggered() );
|
assertTrue( triggerable.wasTriggered() );
|
||||||
assertNull( ( metadata.getEntityBinding( AEntity.class.getName() ) ).getCacheConcurrencyStrategy() );
|
assertFalse( metadata.getEntityBinding( AEntity.class.getName() ).isCached() );
|
||||||
|
|
||||||
serviceRegistry.destroy();
|
serviceRegistry.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,8 +64,10 @@ public class NonRootEntityWithCacheableAnnotationTest {
|
||||||
.addAnnotatedClass( AEntity.class )
|
.addAnnotatedClass( AEntity.class )
|
||||||
.buildMetadata();
|
.buildMetadata();
|
||||||
|
|
||||||
assertTrue( triggerable.wasTriggered() );
|
assertFalse( metadata.getEntityBinding( ABase.class.getName() ).isCached() );
|
||||||
assertNull( ( metadata.getEntityBinding( AEntity.class.getName() ) ).getCacheConcurrencyStrategy() );
|
assertTrue( metadata.getEntityBinding( AEntity.class.getName() ).isCached() );
|
||||||
|
|
||||||
|
assertFalse( triggerable.wasTriggered() );
|
||||||
|
|
||||||
serviceRegistry.destroy();
|
serviceRegistry.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class PolymorphicCacheTest extends BaseCoreFunctionalTestCase {
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
// See HHH-9107
|
// See HHH-9107
|
||||||
try {
|
try {
|
||||||
s.get( CachedItem2.class, item1.getId() );
|
final CachedItem2 tmp = s.get( CachedItem2.class, item1.getId() );
|
||||||
fail( "Expected a WrongClassException to be thrown." );
|
fail( "Expected a WrongClassException to be thrown." );
|
||||||
}
|
}
|
||||||
catch (WrongClassException e) {
|
catch (WrongClassException e) {
|
||||||
|
|
|
@ -28,7 +28,9 @@ import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
|
@ -60,6 +62,8 @@ public class DefaultCacheConcurrencyPropertyTest extends BaseUnitTestCase {
|
||||||
final SessionFactoryImplementor sf = (SessionFactoryImplementor) metadata.buildSessionFactory();
|
final SessionFactoryImplementor sf = (SessionFactoryImplementor) metadata.buildSessionFactory();
|
||||||
try {
|
try {
|
||||||
final EntityPersister persister = sf.getMetamodel().entityPersister( TheEntity.class.getName() );
|
final EntityPersister persister = sf.getMetamodel().entityPersister( TheEntity.class.getName() );
|
||||||
|
assertTrue( persister.canReadFromCache() );
|
||||||
|
assertTrue( persister.canWriteToCache() );
|
||||||
assertNotNull( persister.getCacheAccessStrategy() );
|
assertNotNull( persister.getCacheAccessStrategy() );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|
|
@ -384,6 +384,16 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canReadFromCache() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canWriteToCache() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasCache() {
|
public boolean hasCache() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -6,22 +6,89 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.jpa.compliance.tck2_2;
|
package org.hibernate.test.jpa.compliance.tck2_2;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import javax.persistence.Cacheable;
|
import javax.persistence.Cacheable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Inheritance;
|
import javax.persistence.Inheritance;
|
||||||
import javax.persistence.InheritanceType;
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.SharedCacheMode;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.boot.MetadataSources;
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SubclassOnlyCachingTests extends BaseNonConfigCoreFunctionalTestCase {
|
public class SubclassOnlyCachingTests extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
@Test
|
||||||
|
public void testMapping() {
|
||||||
|
assertThat(
|
||||||
|
sessionFactory().getMetamodel().entityPersister( Person.class ).hasCache(),
|
||||||
|
CoreMatchers.is( false )
|
||||||
|
);
|
||||||
|
assertThat(
|
||||||
|
sessionFactory().getMetamodel().entityPersister( Employee.class ).hasCache(),
|
||||||
|
CoreMatchers.is( false )
|
||||||
|
);
|
||||||
|
assertThat(
|
||||||
|
sessionFactory().getMetamodel().entityPersister( Customer.class ).hasCache(),
|
||||||
|
CoreMatchers.is( true )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnlySubclassIsCached() {
|
||||||
|
final StatisticsImplementor statistics = sessionFactory().getStatistics();
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
s -> s.persist( new Customer( 1, "Acme Corp", "123" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue( sessionFactory().getCache().contains( Customer.class, 1 ) );
|
||||||
|
|
||||||
|
inTransaction(
|
||||||
|
s -> {
|
||||||
|
statistics.clear();
|
||||||
|
|
||||||
|
final Customer customer = s.get( Customer.class, 1 );
|
||||||
|
|
||||||
|
assertTrue( Hibernate.isInitialized( customer ) );
|
||||||
|
|
||||||
|
assertThat( statistics.getSecondLevelCacheHitCount(), CoreMatchers.is(1L) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanupData() {
|
||||||
|
inTransaction(
|
||||||
|
s -> s.createQuery( "delete from Customer" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
super.addSettings( settings );
|
||||||
|
|
||||||
|
settings.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
|
||||||
|
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
||||||
|
settings.put( AvailableSettings.JPA_SHARED_CACHE_MODE, SharedCacheMode.ENABLE_SELECTIVE );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applyMetadataSources(MetadataSources sources) {
|
protected void applyMetadataSources(MetadataSources sources) {
|
||||||
|
@ -31,11 +98,6 @@ public class SubclassOnlyCachingTests extends BaseNonConfigCoreFunctionalTestCas
|
||||||
sources.addAnnotatedClass( Customer.class );
|
sources.addAnnotatedClass( Customer.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnlySubclassIsCached() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity( name = "Person" )
|
@Entity( name = "Person" )
|
||||||
@Table( name = "persons" )
|
@Table( name = "persons" )
|
||||||
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
|
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
|
||||||
|
@ -43,18 +105,43 @@ public class SubclassOnlyCachingTests extends BaseNonConfigCoreFunctionalTestCas
|
||||||
@Id
|
@Id
|
||||||
public Integer id;
|
public Integer id;
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
public Person(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Employee" )
|
||||||
public static class Employee extends Person {
|
public static class Employee extends Person {
|
||||||
public String employeeCode;
|
public String employeeCode;
|
||||||
public String costCenter;
|
public String costCenter;
|
||||||
|
|
||||||
|
public Employee() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
public Employee(Integer id, String name, String employeeCode, String costCenter) {
|
||||||
|
super( id, name );
|
||||||
|
this.employeeCode = employeeCode;
|
||||||
|
this.costCenter = costCenter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Customer" )
|
||||||
@Cacheable()
|
@Cacheable()
|
||||||
public static class Customer extends Person {
|
public static class Customer extends Person {
|
||||||
public String erpCode;
|
public String erpCode;
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(Integer id, String name, String erpCode) {
|
||||||
|
super( id, name );
|
||||||
|
this.erpCode = erpCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -653,6 +653,16 @@ public class CustomPersister implements EntityPersister {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canReadFromCache() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canWriteToCache() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVersionPropertyGenerated() {
|
public boolean isVersionPropertyGenerated() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||||
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.RootClass;
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.tool.schema.internal.HibernateSchemaManagementTool;
|
import org.hibernate.tool.schema.internal.HibernateSchemaManagementTool;
|
||||||
|
@ -70,7 +71,9 @@ public class DiscriminatorMultiTenancyTest extends BaseUnitTestCase {
|
||||||
ms.addAnnotatedClass(Customer.class);
|
ms.addAnnotatedClass(Customer.class);
|
||||||
|
|
||||||
Metadata metadata = ms.buildMetadata();
|
Metadata metadata = ms.buildMetadata();
|
||||||
((RootClass) metadata.getEntityBinding(Customer.class.getName())).setCacheConcurrencyStrategy("read-write");
|
final PersistentClass customerMapping = metadata.getEntityBinding( Customer.class.getName() );
|
||||||
|
customerMapping.setCached( true );
|
||||||
|
((RootClass) customerMapping ).setCacheConcurrencyStrategy( "read-write");
|
||||||
|
|
||||||
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
||||||
tool.injectServices(serviceRegistry);
|
tool.injectServices(serviceRegistry);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||||
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.RootClass;
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.service.spi.Stoppable;
|
import org.hibernate.service.spi.Stoppable;
|
||||||
|
@ -74,7 +75,9 @@ public abstract class AbstractSchemaBasedMultiTenancyTest<T extends MultiTenantC
|
||||||
ms.addAnnotatedClass( Invoice.class );
|
ms.addAnnotatedClass( Invoice.class );
|
||||||
|
|
||||||
Metadata metadata = ms.buildMetadata();
|
Metadata metadata = ms.buildMetadata();
|
||||||
( (RootClass) metadata.getEntityBinding( Customer.class.getName() ) ).setCacheConcurrencyStrategy( "read-write" );
|
final PersistentClass customerMapping = metadata.getEntityBinding( Customer.class.getName() );
|
||||||
|
customerMapping.setCached( true );
|
||||||
|
( (RootClass) customerMapping ).setCacheConcurrencyStrategy( "read-write" );
|
||||||
|
|
||||||
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
||||||
tool.injectServices( serviceRegistry );
|
tool.injectServices( serviceRegistry );
|
||||||
|
|
|
@ -344,6 +344,7 @@ public class BaseNonConfigCoreFunctionalTestCase extends BaseUnitTestCase {
|
||||||
|
|
||||||
if ( !hasLob ) {
|
if ( !hasLob ) {
|
||||||
( ( RootClass) entityBinding ).setCacheConcurrencyStrategy( getCacheConcurrencyStrategy() );
|
( ( RootClass) entityBinding ).setCacheConcurrencyStrategy( getCacheConcurrencyStrategy() );
|
||||||
|
entityBinding.setCached( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue