correct implementation of JPA SharedCacheMode for .hbm.xml
- even though I hate most of its members, I think NONE is pretty useful - anyway we may as well make it work, since it's trivial
This commit is contained in:
parent
1db1c08d3b
commit
327342b39e
|
@ -9,9 +9,9 @@ package org.hibernate.boot.model;
|
|||
/**
|
||||
* An enumeration of truth values.
|
||||
*
|
||||
* @implNote Yes this *could* be handled with Boolean, but then
|
||||
* you run into potential problems with unwanted auto-unboxing
|
||||
* and {@linkplain NullPointerException NPE}.
|
||||
* @implNote Sure, this could be handled with {@code Boolean}, but
|
||||
* that option is vulnerable to unwanted auto-unboxing
|
||||
* and {@link NullPointerException}s.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
|
|
@ -1470,39 +1470,32 @@ public class EntityBinder {
|
|||
return false;
|
||||
}
|
||||
switch ( effectiveCache.include().toLowerCase( Locale.ROOT ) ) {
|
||||
case "all": {
|
||||
case "all":
|
||||
return true;
|
||||
}
|
||||
case "non-lazy": {
|
||||
case "non-lazy":
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
default:
|
||||
throw new AnnotationException( "Class '" + annotatedClass.getName()
|
||||
+ "' has a '@Cache' with undefined option 'include=\"" + effectiveCache.include() + "\"'" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCacheable(SharedCacheMode sharedCacheMode, Cacheable explicitCacheableAnn) {
|
||||
switch (sharedCacheMode) {
|
||||
case ALL: {
|
||||
switch ( sharedCacheMode ) {
|
||||
case ALL:
|
||||
// all entities should be cached
|
||||
return true;
|
||||
}
|
||||
case ENABLE_SELECTIVE: {
|
||||
case ENABLE_SELECTIVE:
|
||||
// only entities with @Cacheable(true) should be cached
|
||||
return explicitCacheableAnn != null && explicitCacheableAnn.value();
|
||||
}
|
||||
case DISABLE_SELECTIVE: {
|
||||
case DISABLE_SELECTIVE:
|
||||
// only entities with @Cacheable(false) should not be cached
|
||||
return explicitCacheableAnn == null || explicitCacheableAnn.value();
|
||||
}
|
||||
default: {
|
||||
default:
|
||||
// treat both NONE and UNSPECIFIED the same
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String resolveCacheConcurrencyStrategy(CacheConcurrencyStrategy strategy) {
|
||||
final org.hibernate.cache.spi.access.AccessType accessType = strategy.toAccessType();
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
|||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
|
@ -76,33 +78,32 @@ public class Helper {
|
|||
|
||||
public static Caching createCaching(JaxbHbmCacheType cacheElement) {
|
||||
if ( cacheElement == null ) {
|
||||
// I'd really rather this be UNKNOWN, but the annotation version resolves this to TRUE/FALSE
|
||||
return new Caching( TruthValue.FALSE );
|
||||
return new Caching( TruthValue.UNKNOWN );
|
||||
}
|
||||
|
||||
final boolean cacheLazyProps = cacheElement.getInclude() == null
|
||||
|| !"non-lazy".equals( cacheElement.getInclude().value() );
|
||||
|
||||
else {
|
||||
return new Caching(
|
||||
cacheElement.getRegion(),
|
||||
cacheElement.getUsage(),
|
||||
cacheLazyProps,
|
||||
cacheElement.getInclude() == null
|
||||
|| !"non-lazy".equals( cacheElement.getInclude().value() ),
|
||||
TruthValue.TRUE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static Caching createNaturalIdCaching(JaxbHbmNaturalIdCacheType cacheElement) {
|
||||
if ( cacheElement == null ) {
|
||||
return new Caching( TruthValue.UNKNOWN );
|
||||
}
|
||||
|
||||
else {
|
||||
return new Caching(
|
||||
StringHelper.nullIfEmpty( cacheElement.getRegion() ),
|
||||
nullIfEmpty( cacheElement.getRegion() ),
|
||||
null,
|
||||
false,
|
||||
TruthValue.TRUE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getPropertyAccessorName(String access, boolean isEmbedded, String defaultAccess) {
|
||||
return getValue( access, isEmbedded ? "embedded" : defaultAccess );
|
||||
|
|
|
@ -96,6 +96,7 @@ import org.hibernate.boot.spi.InFlightMetadataCollector.EntityTableXref;
|
|||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
|
||||
import org.hibernate.boot.spi.SecondPass;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
|
@ -203,24 +204,20 @@ public class ModelBinder {
|
|||
.addEntityBinding( rootEntityDescriptor );
|
||||
|
||||
switch ( hierarchySource.getHierarchyInheritanceType() ) {
|
||||
case NO_INHERITANCE: {
|
||||
case NO_INHERITANCE:
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
case DISCRIMINATED: {
|
||||
case DISCRIMINATED:
|
||||
bindDiscriminatorSubclassEntities( hierarchySource.getRoot(), rootEntityDescriptor );
|
||||
break;
|
||||
}
|
||||
case JOINED: {
|
||||
case JOINED:
|
||||
bindJoinedSubclassEntities( hierarchySource.getRoot(), rootEntityDescriptor );
|
||||
break;
|
||||
}
|
||||
case UNION: {
|
||||
case UNION:
|
||||
bindUnionSubclassEntities( hierarchySource.getRoot(), rootEntityDescriptor );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindRootEntity(EntityHierarchySourceImpl hierarchySource, RootClass rootEntityDescriptor) {
|
||||
final MappingDocument mappingDocument = hierarchySource.getRoot().sourceMappingDocument();
|
||||
|
@ -293,51 +290,42 @@ public class ModelBinder {
|
|||
}
|
||||
|
||||
private void applyCaching(MappingDocument mappingDocument, Caching caching, RootClass rootEntityDescriptor) {
|
||||
if ( caching == null || caching.getRequested() == TruthValue.UNKNOWN ) {
|
||||
// see if JPA's SharedCacheMode indicates we should implicitly apply caching
|
||||
//
|
||||
// here we only really look for ALL. Ideally we could look at NONE too as a means
|
||||
// to selectively disable all caching, but historically hbm.xml mappings were processed
|
||||
// outside this concept and whether to cache or not was defined wholly by what
|
||||
// is defined in the mapping document. So for backwards compatibility we
|
||||
// do not consider ENABLE_SELECTIVE nor DISABLE_SELECTIVE here.
|
||||
//
|
||||
// Granted, ALL was not historically considered either, but I have a practical
|
||||
// reason for wanting to support this... our legacy tests built using
|
||||
// Configuration applied a similar logic but that capability is no longer
|
||||
// accessible from Configuration
|
||||
if ( isCacheEnabled( mappingDocument, caching ) ) {
|
||||
rootEntityDescriptor.setCacheConcurrencyStrategy( getConcurrencyStrategy( mappingDocument, caching ).getExternalName() );
|
||||
rootEntityDescriptor.setCacheRegionName( caching == null ? null : caching.getRegion() );
|
||||
rootEntityDescriptor.setLazyPropertiesCacheable( caching == null || caching.isCacheLazyProperties() );
|
||||
rootEntityDescriptor.setCached( true );
|
||||
}
|
||||
}
|
||||
|
||||
private static AccessType getConcurrencyStrategy(MappingDocument mappingDocument, Caching caching) {
|
||||
return caching == null || caching.getAccessType() == null
|
||||
? mappingDocument.getBuildingOptions().getImplicitCacheAccessType()
|
||||
: caching.getAccessType();
|
||||
}
|
||||
|
||||
private static boolean isCacheEnabled(MappingDocument mappingDocument, Caching caching) {
|
||||
switch ( mappingDocument.getBuildingOptions().getSharedCacheMode() ) {
|
||||
case UNSPECIFIED:
|
||||
case ENABLE_SELECTIVE:
|
||||
// this is default behavior for hbm.xml
|
||||
return caching != null && caching.getRequested().toBoolean(false);
|
||||
case NONE:
|
||||
// this option is actually really useful
|
||||
return false;
|
||||
case ALL:
|
||||
caching = new Caching(
|
||||
null,
|
||||
mappingDocument.getBuildingOptions().getImplicitCacheAccessType(),
|
||||
false,
|
||||
TruthValue.UNKNOWN
|
||||
);
|
||||
break;
|
||||
case NONE: // Ideally we'd disable all caching...
|
||||
case ENABLE_SELECTIVE: // this is default behavior for hbm.xml
|
||||
case DISABLE_SELECTIVE: // really makes no sense for hbm.xml
|
||||
default: // null or UNSPECIFIED, nothing to do. IMO for hbm.xml this is equivalent to ENABLE_SELECTIVE
|
||||
// do nothing
|
||||
// goes completely against the whole ideology we have for
|
||||
// caching, and so it hurts me to support it here
|
||||
return true;
|
||||
case DISABLE_SELECTIVE:
|
||||
// makes no sense for hbm.xml, and also goes against our
|
||||
// ideology, and so it hurts me to support it here
|
||||
return caching == null || caching.getRequested().toBoolean(true);
|
||||
default:
|
||||
throw new AssertionFailure( "unknown SharedCacheMode" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( caching == null || caching.getRequested() == TruthValue.FALSE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( caching.getAccessType() != null ) {
|
||||
rootEntityDescriptor.setCacheConcurrencyStrategy( caching.getAccessType().getExternalName() );
|
||||
}
|
||||
else {
|
||||
rootEntityDescriptor.setCacheConcurrencyStrategy( mappingDocument.getBuildingOptions().getImplicitCacheAccessType().getExternalName() );
|
||||
}
|
||||
rootEntityDescriptor.setCacheRegionName( caching.getRegion() );
|
||||
rootEntityDescriptor.setLazyPropertiesCacheable( caching.isCacheLazyProperties() );
|
||||
rootEntityDescriptor.setCached( caching.getRequested() != TruthValue.UNKNOWN );
|
||||
}
|
||||
|
||||
private void bindEntityIdentifier(
|
||||
MappingDocument mappingDocument,
|
||||
EntityHierarchySourceImpl hierarchySource,
|
||||
|
@ -1553,50 +1541,10 @@ public class ModelBinder {
|
|||
}
|
||||
|
||||
private void applyCaching(MappingDocument mappingDocument, Caching caching, Collection collection) {
|
||||
if ( caching == null || caching.getRequested() == TruthValue.UNKNOWN ) {
|
||||
// see if JPA's SharedCacheMode indicates we should implicitly apply caching
|
||||
switch ( mappingDocument.getBuildingOptions().getSharedCacheMode() ) {
|
||||
case ALL: {
|
||||
caching = new Caching(
|
||||
null,
|
||||
mappingDocument.getBuildingOptions().getImplicitCacheAccessType(),
|
||||
false,
|
||||
TruthValue.UNKNOWN
|
||||
);
|
||||
break;
|
||||
if ( isCacheEnabled( mappingDocument, caching ) ) {
|
||||
collection.setCacheConcurrencyStrategy( getConcurrencyStrategy( mappingDocument, caching ).getExternalName() );
|
||||
collection.setCacheRegionName( caching == null ? null : caching.getRegion() );
|
||||
}
|
||||
case NONE: {
|
||||
// Ideally we'd disable all caching...
|
||||
break;
|
||||
}
|
||||
case ENABLE_SELECTIVE: {
|
||||
// this is default behavior for hbm.xml
|
||||
break;
|
||||
}
|
||||
case DISABLE_SELECTIVE: {
|
||||
// really makes no sense for hbm.xml
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// null or UNSPECIFIED, nothing to do. IMO for hbm.xml this is equivalent
|
||||
// to ENABLE_SELECTIVE
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( caching == null || caching.getRequested() == TruthValue.FALSE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( caching.getAccessType() != null ) {
|
||||
collection.setCacheConcurrencyStrategy( caching.getAccessType().getExternalName() );
|
||||
}
|
||||
else {
|
||||
collection.setCacheConcurrencyStrategy( mappingDocument.getBuildingOptions().getImplicitCacheAccessType().getExternalName() );
|
||||
}
|
||||
collection.setCacheRegionName( caching.getRegion() );
|
||||
// collection.setCachingExplicitlyRequested( caching.getRequested() != TruthValue.UNKNOWN );
|
||||
}
|
||||
|
||||
private Identifier determineTable(
|
||||
|
|
Loading…
Reference in New Issue