HHH-7384 binding natural id cache

HHH-6354 Implement natural ID mapping
This commit is contained in:
Strong Liu 2012-06-26 14:04:26 +08:00
parent b2e0b5032d
commit 1b1af382de
40 changed files with 354 additions and 135 deletions

View File

@ -746,6 +746,43 @@ public final class SessionFactoryImpl
allCacheRegions.put( cacheRegionName, entityRegion );
}
}
NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null;
if ( settings.isSecondLevelCacheEnabled() &&
rootEntityBinding.getHierarchyDetails().getNaturalIdCaching() != null &&
model.getHierarchyDetails().getNaturalIdCaching() != null ) {
final String naturalIdCacheRegionName = cacheRegionPrefix + rootEntityBinding.getHierarchyDetails()
.getNaturalIdCaching()
.getRegion();
naturalIdAccessStrategy = (NaturalIdRegionAccessStrategy) entityAccessStrategies.get(
naturalIdCacheRegionName
);
if ( naturalIdAccessStrategy == null ) {
final CacheDataDescriptionImpl naturaIdCacheDataDescription = CacheDataDescriptionImpl.decode( model );
NaturalIdRegion naturalIdRegion = null;
try {
naturalIdRegion = settings.getRegionFactory()
.buildNaturalIdRegion(
naturalIdCacheRegionName,
properties,
naturaIdCacheDataDescription
);
}
catch ( UnsupportedOperationException e ) {
LOG.warnf(
"Shared cache region factory [%s] does not support natural id caching; " +
"shared NaturalId caching will be disabled for not be enabled for %s",
settings.getRegionFactory().getClass().getName(),
model.getEntity().getName()
);
}
if ( naturalIdRegion != null ) {
naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( settings.getRegionFactory().getDefaultAccessType() );
entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy );
allCacheRegions.put( naturalIdCacheRegionName, naturalIdRegion );
}
}
}
EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister(
model, accessStrategy, this, metadata
);

View File

@ -279,6 +279,7 @@ public class Binder {
propertyAccessorName( attributeSource ),
attributeSource.isIncludedInOptimisticLocking(),
attributeSource.isLazy(),
attributeSource.getNaturalIdMutability(),
createMetaAttributeContext( attributeBindingContainer, attributeSource ),
attributeSource.getGeneration() );
final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor();
@ -326,6 +327,7 @@ public class Binder {
propertyAccessorName( attributeSource ),
attributeSource.isIncludedInOptimisticLocking(),
attributeSource.isLazy(),
attributeSource.getNaturalIdMutability(),
createMetaAttributeContext( attributeBindingContainer, attributeSource ) );
bindAttributes( attributeBinding, attributeSource );
return attributeBinding;
@ -387,6 +389,7 @@ public class Binder {
propertyAccessorName( attributeSource ),
attributeSource.isIncludedInOptimisticLocking(),
attributeSource.isLazy(),
attributeSource.getNaturalIdMutability(),
createMetaAttributeContext( attributeBindingContainer, attributeSource ),
( SingularAttributeBinding ) referencedAttributeBinding,
relationalValueBindings );
@ -1001,6 +1004,7 @@ public class Binder {
bindIdentifierGenerator( rootEntityBinding );
bindMultiTenancy( rootEntityBinding, rootEntitySource );
rootEntityBinding.getHierarchyDetails().setCaching( rootEntitySource.getCaching() );
rootEntityBinding.getHierarchyDetails().setNaturalIdCaching( rootEntitySource.getNaturalIdCaching() );
rootEntityBinding.getHierarchyDetails().setExplicitPolymorphism( rootEntitySource.isExplicitPolymorphism() );
rootEntityBinding.getHierarchyDetails().setOptimisticLockStyle( rootEntitySource.getOptimisticLockStyle() );
rootEntityBinding.setMutable( rootEntitySource.isMutable() );

View File

@ -124,12 +124,7 @@ public class BasicAttribute extends MappedAttribute {
annotations,
HibernateDotNames.SOURCE
);
if ( sourceAnnotation != null ) {
versionSourceType = JandexHelper.getEnumValue( sourceAnnotation, "value", SourceType.class );
}
else {
versionSourceType = null;
}
this.versionSourceType = sourceAnnotation !=null ? JandexHelper.getEnumValue( sourceAnnotation, "value", SourceType.class ) : null;
}
else {
versionSourceType = null;

View File

@ -37,6 +37,7 @@ import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.internal.source.annotations.attribute.type.AttributeTypeResolver;
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
/**
* Base class for the different types of mapped attributes
@ -81,6 +82,11 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
*/
private final boolean isId;
/**
* Is this property a natural id property and what's the mutability it is.
*/
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
/**
* Whether a change of the property's value triggers a version increment of the entity (in case of optimistic
* locking).
@ -98,7 +104,9 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
*/
private final EntityBindingContext context;
MappedAttribute(String name, Class<?> attributeType, AttributeNature attributeNature, String accessType, Map<DotName, List<AnnotationInstance>> annotations, EntityBindingContext context) {
MappedAttribute(String name, Class<?> attributeType, AttributeNature attributeNature,
String accessType, Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
this.context = context;
this.annotations = annotations;
this.name = name;
@ -116,6 +124,7 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
this.isOptimisticLockable = checkOptimisticLockAnnotation();
this.checkCondition = checkCheckAnnotation();
this.naturalIdMutability = checkNaturalId();
checkColumnAnnotations( annotations );
}
@ -151,6 +160,10 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
return isOptimisticLockable;
}
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}
public AttributeNature getAttributeNature() {
return attributeNature;
}
@ -198,6 +211,18 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
return triggersVersionIncrement;
}
private SingularAttributeBinding.NaturalIdMutability checkNaturalId() {
final AnnotationInstance naturalIdAnnotation = JandexHelper.getSingleAnnotation(
annotations,
HibernateDotNames.NATURAL_ID
);
if ( naturalIdAnnotation == null ) {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
final boolean mutable = naturalIdAnnotation.value("mutable") == null ? false : naturalIdAnnotation.value( "mutable" ).asBoolean();
return mutable ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE;
}
private void checkColumnAnnotations(Map<DotName, List<AnnotationInstance>> annotations) {
columnValues = new ArrayList<Column>();

View File

@ -29,6 +29,7 @@ import java.util.List;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.internal.source.annotations.attribute.type.ExplicitHibernateTypeSourceImpl;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -72,8 +73,8 @@ public class SingularAttributeSourceImpl implements SingularAttributeSource {
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return null; // todo : implement proper method body
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return attribute.getNaturalIdMutability();
}
@Override

View File

@ -36,6 +36,7 @@ import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.internal.source.annotations.util.EnumConversionHelper;
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.relational.Value;
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
import org.hibernate.metamodel.spi.source.SingularAttributeNature;
@ -59,11 +60,6 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
return SingularAttributeNature.MANY_TO_ONE;
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return null; // todo : implement proper method body
}
@Override
public String getReferencedEntityName() {
return associationAttribute.getReferencedEntityType();
@ -111,12 +107,7 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem
@Override
public FetchTiming getFetchTiming() {
if ( associationAttribute.isLazy() ) {
return FetchTiming.DELAYED;
}
else {
return FetchTiming.IMMEDIATE;
}
return associationAttribute.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE;
}
@Override

View File

@ -23,6 +23,7 @@
*/
package org.hibernate.metamodel.internal.source.annotations.attribute;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.VersionAttributeSource;
/**
@ -44,4 +45,9 @@ public class VersionAttributeSourceImpl
public String getUnsavedValue() {
return null;
}
@Override
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
}

View File

@ -32,6 +32,7 @@ import java.util.Map;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.Value;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride;
@ -44,7 +45,6 @@ import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
import org.hibernate.metamodel.spi.source.SingularAttributeNature;
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
/**
* Annotation backed implementation of {@code ComponentAttributeSource}.
@ -63,12 +63,7 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
this.embeddableClass = embeddableClass;
this.classReference = new Value<Class<?>>( embeddableClass.getConfiguredClass() );
this.attributeOverrides = attributeOverrides;
if ( StringHelper.isEmpty( parentPath ) ) {
path = embeddableClass.getEmbeddedAttributeName();
}
else {
path = parentPath + "." + embeddableClass.getEmbeddedAttributeName();
}
this.path = StringHelper.isEmpty( parentPath ) ? embeddableClass.getEmbeddedAttributeName() : parentPath + "." + embeddableClass.getEmbeddedAttributeName();
}
@Override
@ -190,8 +185,8 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return null; // todo : implement proper method body
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return embeddableClass.getNaturalIdMutability();
}
@Override

View File

@ -59,6 +59,7 @@ import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotName
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.internal.source.annotations.util.ReflectionHelper;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.MappingException;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
@ -365,7 +366,7 @@ public class ConfiguredClass {
// when the access type of the class is FIELD
// overriding access annotations must be placed on properties AND have the access type PROPERTY
if ( AccessType.FIELD.equals( classAccessType ) ) {
if ( !( annotationTarget instanceof MethodInfo ) ) {
if ( !MethodInfo.class.isInstance( annotationTarget ) ) {
LOG.tracef(
"The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
"@Access has to be placed on the property (getter)", classInfo.name().toString()
@ -387,7 +388,7 @@ public class ConfiguredClass {
// when the access type of the class is PROPERTY
// overriding access annotations must be placed on fields and have the access type FIELD
if ( AccessType.PROPERTY.equals( classAccessType ) ) {
if ( !( annotationTarget instanceof FieldInfo ) ) {
if ( !FieldInfo.class.isInstance( annotationTarget ) ) {
LOG.tracef(
"The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
"@Access has to be placed on the field ", classInfo.name().toString()
@ -410,13 +411,7 @@ public class ConfiguredClass {
private void createMappedAttribute(Member member, ResolvedTypeWithMembers resolvedType, AccessType accessType) {
final String attributeName = ReflectionHelper.getPropertyName( member );
ResolvedMember[] resolvedMembers;
if ( member instanceof Field ) {
resolvedMembers = resolvedType.getMemberFields();
}
else {
resolvedMembers = resolvedType.getMemberMethods();
}
final ResolvedMember[] resolvedMembers = Field.class.isInstance( member ) ? resolvedType.getMemberFields() : resolvedType.getMemberMethods();
Class<?> attributeType = (Class<?>) findResolvedType( member.getName(), resolvedMembers );
final Map<DotName, List<AnnotationInstance>> annotations = JandexHelper.getMemberAnnotations(
classInfo, member.getName()
@ -449,13 +444,13 @@ public class ConfiguredClass {
throw new NotYetImplementedException( "Element collections must still be implemented." );
}
case EMBEDDED_ID: {
BasicAttribute attribute = BasicAttribute.createSimpleAttribute(
final BasicAttribute attribute = BasicAttribute.createSimpleAttribute(
attributeName, attributeType, attributeNature, annotations, accessTypeString, getLocalBindingContext()
);
idAttributeMap.put( attributeName, attribute );
}
case EMBEDDED: {
AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation(
final AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation(
getClassInfo(),
HibernateDotNames.TARGET
);
@ -464,13 +459,13 @@ public class ConfiguredClass {
JandexHelper.getValue( targetAnnotation, "value", String.class )
);
}
resolveEmbeddable( attributeName, attributeType );
resolveEmbeddable( attributeName, attributeType, annotations );
break;
}
// OneToOne, OneToMany, ManyToOne, ManyToMany
case ONE_TO_ONE:
case MANY_TO_ONE: {
AssociationAttribute attribute = AssociationAttribute.createAssociationAttribute(
final AssociationAttribute attribute = AssociationAttribute.createAssociationAttribute(
attributeName,
attributeType,
attributeNature,
@ -498,10 +493,10 @@ public class ConfiguredClass {
}
}
private void resolveEmbeddable(String attributeName, Class<?> type) {
ClassInfo embeddableClassInfo = localBindingContext.getClassInfo( type.getName() );
private void resolveEmbeddable(String attributeName, Class<?> type, Map<DotName, List<AnnotationInstance>> annotations) {
final ClassInfo embeddableClassInfo = localBindingContext.getClassInfo( type.getName() );
if ( embeddableClassInfo == null ) {
String msg = String.format(
final String msg = String.format(
"Attribute '%s#%s' is annotated with @Embedded, but '%s' does not seem to be annotated " +
"with @Embeddable. Are all annotated classes added to the configuration?",
getConfiguredClass().getSimpleName(),
@ -512,10 +507,26 @@ public class ConfiguredClass {
}
localBindingContext.resolveAllTypes( type.getName() );
EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy(
AnnotationInstance naturalIdAnnotationInstance = JandexHelper.getSingleAnnotation(
annotations,
HibernateDotNames.NATURAL_ID
);
SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
if ( naturalIdAnnotationInstance != null ) {
naturalIdMutability = JandexHelper.getValue(
naturalIdAnnotationInstance,
"mutable",
Boolean.class
) ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE;
}
else {
naturalIdMutability = SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
final EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy(
localBindingContext.<Object>locateClassByName( embeddableClassInfo.toString() ),
attributeName,
classAccessType,
naturalIdMutability,
localBindingContext
);
embeddedClasses.put( attributeName, hierarchy.getLeaf() );
@ -570,14 +581,14 @@ public class ConfiguredClass {
discoveredAttributeTypes.put( AttributeNature.ELEMENT_COLLECTION, elementCollection );
}
if ( discoveredAttributeTypes.size() == 0 ) {
return AttributeNature.BASIC;
}
else if ( discoveredAttributeTypes.size() == 1 ) {
return discoveredAttributeTypes.keySet().iterator().next();
}
else {
throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() );
int size = discoveredAttributeTypes.size();
switch ( size ){
case 0:
return AttributeNature.BASIC;
case 1:
return discoveredAttributeTypes.keySet().iterator().next();
default:
throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() );
}
}

View File

@ -31,6 +31,7 @@ import org.jboss.jandex.ClassInfo;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
/**
* Represents the information about an entity annotated with {@code @Embeddable}.
@ -40,15 +41,18 @@ import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
public class EmbeddableClass extends ConfiguredClass {
private final String embeddedAttributeName;
private final String parentReferencingAttributeName;
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
public EmbeddableClass(
ClassInfo classInfo,
String embeddedAttributeName,
ConfiguredClass parent,
AccessType defaultAccessType,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
AnnotationBindingContext context) {
super( classInfo, defaultAccessType, parent, context );
this.embeddedAttributeName = embeddedAttributeName;
this.naturalIdMutability = naturalIdMutability;
this.parentReferencingAttributeName = checkParentAnnotation();
}
@ -57,12 +61,7 @@ public class EmbeddableClass extends ConfiguredClass {
getClassInfo(),
HibernateDotNames.PARENT
);
if ( parentAnnotation == null ) {
return null;
}
else {
return JandexHelper.getPropertyName( parentAnnotation.target() );
}
return parentAnnotation == null? null : JandexHelper.getPropertyName( parentAnnotation.target() );
}
public String getEmbeddedAttributeName() {
@ -72,6 +71,10 @@ public class EmbeddableClass extends ConfiguredClass {
public String getParentReferencingAttributeName() {
return parentReferencingAttributeName;
}
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}
}

View File

@ -26,15 +26,19 @@ package org.hibernate.metamodel.internal.source.annotations.entity;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.AccessType;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.hibernate.AssertionFailure;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
/**
* Contains information about the access and inheritance type for all classes within a class hierarchy.
@ -55,7 +59,9 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
*
* @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity.
*/
public static EmbeddableHierarchy createEmbeddableHierarchy(Class<?> embeddableClass, String propertyName, AccessType accessType, AnnotationBindingContext context) {
public static EmbeddableHierarchy createEmbeddableHierarchy(Class<?> embeddableClass, String propertyName,
AccessType accessType,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability, AnnotationBindingContext context) {
ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() );
if ( embeddableClassInfo == null ) {
@ -76,11 +82,12 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
);
}
List<ClassInfo> classInfoList = new ArrayList<ClassInfo>();
ClassInfo tmpClassInfo;
Class<?> clazz = embeddableClass;
while ( clazz != null && !clazz.equals( Object.class ) ) {
tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) );
ClassInfo tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) );
clazz = clazz.getSuperclass();
if ( tmpClassInfo == null ) {
continue;
@ -92,6 +99,7 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
return new EmbeddableHierarchy(
classInfoList,
propertyName,
naturalIdMutability,
context,
accessType
);
@ -101,6 +109,7 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
private EmbeddableHierarchy(
List<ClassInfo> classInfoList,
String propertyName,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
AnnotationBindingContext context,
AccessType defaultAccessType) {
this.defaultAccessType = defaultAccessType;
@ -108,12 +117,11 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
// the resolved type for the top level class in the hierarchy
context.resolveAllTypes( classInfoList.get( classInfoList.size() - 1 ).name().toString() );
embeddables = new ArrayList<EmbeddableClass>();
this.embeddables = new ArrayList<EmbeddableClass>();
ConfiguredClass parent = null;
EmbeddableClass embeddable;
for ( ClassInfo info : classInfoList ) {
embeddable = new EmbeddableClass(
info, propertyName, parent, defaultAccessType, context
EmbeddableClass embeddable = new EmbeddableClass(
info, propertyName, parent, defaultAccessType,naturalIdMutability, context
);
embeddables.add( embeddable );
parent = embeddable;

View File

@ -57,6 +57,7 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.annotations.PolymorphismType;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.attribute.Column;
import org.hibernate.metamodel.internal.source.annotations.attribute.FormulaValue;
@ -80,6 +81,7 @@ import org.hibernate.metamodel.spi.source.TableSpecificationSource;
* @author Hardy Ferentschik
*/
public class EntityClass extends ConfiguredClass {
private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId";
private final IdType idType;
private final InheritanceType inheritanceType;
@ -98,6 +100,7 @@ public class EntityClass extends ConfiguredClass {
private String whereClause;
private String rowId;
private Caching caching;
private Caching naturalIdCaching;
private boolean isDynamicInsert;
private boolean isDynamicUpdate;
private boolean isSelectBeforeUpdate;
@ -204,6 +207,10 @@ public class EntityClass extends ConfiguredClass {
return caching;
}
public Caching getNaturalIdCaching(){
return naturalIdCaching;
}
public TableSpecificationSource getPrimaryTableSource() {
// todo : this is different from hbm which returns null if "!definesItsOwnTable()"
if ( definesItsOwnTable() ) {
@ -484,6 +491,8 @@ public class EntityClass extends ConfiguredClass {
caching = determineCachingSettings();
naturalIdCaching = determineNaturalIdCachingSettings(caching);
// see HHH-6397
isDynamicInsert =
hibernateEntityAnnotation != null
@ -525,6 +534,28 @@ public class EntityClass extends ConfiguredClass {
this.customPersister = entityPersisterClass;
}
private Caching determineNaturalIdCachingSettings(final Caching entityCache) {
final AnnotationInstance naturalIdCacheAnnotation = JandexHelper.getSingleAnnotation(
getClassInfo(),
HibernateDotNames.NATURAL_ID_CACHE
);
if ( naturalIdCacheAnnotation == null ) {
return null;
}
final String region;
if ( naturalIdCacheAnnotation.value( "region" ) == null || StringHelper.isEmpty(
naturalIdCacheAnnotation.value(
"region"
).asString()
) ) {
region = entityCache == null ? getEntityName() + NATURAL_ID_CACHE_SUFFIX : entityCache.getRegion() + NATURAL_ID_CACHE_SUFFIX;
}
else {
region = naturalIdCacheAnnotation.value( "region" ).asString();
}
return new Caching( region, null, false );
}
private Caching determineCachingSettings() {
final AnnotationInstance hibernateCacheAnnotation = JandexHelper.getSingleAnnotation(
getClassInfo(), HibernateDotNames.CACHE

View File

@ -146,6 +146,11 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity
return getEntityClass().getCaching();
}
@Override
public Caching getNaturalIdCaching() {
return getEntityClass().getNaturalIdCaching();
}
private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource {
private final ComponentAttributeSourceImpl componentAttributeSource;

View File

@ -72,6 +72,7 @@ import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OptimisticLock;
@ -156,6 +157,7 @@ public interface HibernateDotNames {
DotName NAMED_QUERIES = DotName.createSimple( NamedQueries.class.getName() );
DotName NAMED_QUERY = DotName.createSimple( NamedQuery.class.getName() );
DotName NATURAL_ID = DotName.createSimple( NaturalId.class.getName() );
DotName NATURAL_ID_CACHE = DotName.createSimple( NaturalIdCache.class.getName() );
DotName NOT_FOUND = DotName.createSimple( NotFound.class.getName() );
DotName ON_DELETE = DotName.createSimple( OnDelete.class.getName() );
DotName OPTIMISTIC_LOCK = DotName.createSimple( OptimisticLock.class.getName() );

View File

@ -35,6 +35,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToManyElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbOneToOneElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement;
import org.hibernate.internal.util.Value;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.AttributeSource;
import org.hibernate.metamodel.spi.source.AttributeSourceContainer;
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
@ -51,7 +52,7 @@ public abstract class AbstractComponentAttributeSourceImpl extends AbstractHbmSo
private final ComponentSourceElement componentSourceElement;
private final AttributeSourceContainer parentContainer;
private final List<AttributeSource> subAttributeSources;
private final NaturalIdMutability naturalIdMutability;
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
private final Value<Class<?>> componentClassReference;
private final String logicalTableName;
private final String path;
@ -61,7 +62,7 @@ public abstract class AbstractComponentAttributeSourceImpl extends AbstractHbmSo
ComponentSourceElement componentSourceElement,
AttributeSourceContainer parentContainer,
String logicalTableName,
NaturalIdMutability naturalIdMutability) {
SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.componentSourceElement = componentSourceElement;
this.parentContainer = parentContainer;
@ -212,7 +213,7 @@ public abstract class AbstractComponentAttributeSourceImpl extends AbstractHbmSo
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}

View File

@ -48,6 +48,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement;
import org.hibernate.internal.jaxb.mapping.hbm.JoinElementSource;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.AttributeSource;
import org.hibernate.metamodel.spi.source.ConstraintSource;
import org.hibernate.metamodel.spi.source.EntitySource;
@ -55,7 +56,6 @@ import org.hibernate.metamodel.spi.source.JpaCallbackSource;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.SecondaryTableSource;
import org.hibernate.metamodel.spi.source.SingularAttributeSource;
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
/**
@ -109,7 +109,7 @@ public abstract class AbstractEntitySourceImpl
attributeSources,
entityElement.getPropertyOrManyToOneOrOneToOne(),
null,
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID
);
return attributeSources;
}
@ -118,7 +118,7 @@ public abstract class AbstractEntitySourceImpl
List<AttributeSource> results,
List attributeElements,
String logicalTableName,
SingularAttributeSource.NaturalIdMutability naturalIdMutability) {
SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
for ( Object attributeElement : attributeElements ) {
results.add( buildAttributeSource( attributeElement, logicalTableName, naturalIdMutability ) );
}
@ -127,7 +127,7 @@ public abstract class AbstractEntitySourceImpl
protected AttributeSource buildAttributeSource(
Object attributeElement,
String logicalTableName,
SingularAttributeSource.NaturalIdMutability naturalIdMutability) {
SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
if ( JaxbPropertyElement.class.isInstance( attributeElement ) ) {
return new PropertyAttributeSourceImpl(
sourceMappingDocument(),
@ -215,7 +215,7 @@ public abstract class AbstractEntitySourceImpl
attributeSources,
joinElement.getPropertyOrManyToOneOrComponent(),
logicalTableName,
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID
);
}
return secondaryTableSources;

View File

@ -32,7 +32,6 @@ import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.internal.jaxb.mapping.hbm.PluralAttributeElement;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.Value;
import org.hibernate.metamodel.spi.binding.Caching;
import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.source.AttributeSourceContainer;
@ -57,7 +56,7 @@ public abstract class AbstractPluralAttributeSourceImpl
private final PluralAttributeKeySource keySource;
private final PluralAttributeElementSource elementSource;
private final Value<Caching> cachingHolder;
private final Caching caching;
protected AbstractPluralAttributeSourceImpl(
MappingDocument sourceMappingDocument,
@ -74,7 +73,10 @@ public abstract class AbstractPluralAttributeSourceImpl
);
this.elementSource = interpretElementType();
this.cachingHolder = Helper.createCachingHolder( pluralAttributeElement.getCache(), StringHelper.qualify( container().getPath(), getName() ) );
this.caching = Helper.createCaching(
pluralAttributeElement.getCache(),
StringHelper.qualify( container().getPath(), getName() )
);
this.typeInformation = new ExplicitHibernateTypeSource() {
@Override
@ -170,7 +172,7 @@ public abstract class AbstractPluralAttributeSourceImpl
@Override
public Caching getCaching() {
return cachingHolder.getValue();
return caching;
}
@Override

View File

@ -31,6 +31,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbTuplizerElement;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.AttributeSource;
import org.hibernate.metamodel.spi.source.AttributeSourceContainer;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -44,7 +45,7 @@ class ComponentAttributeSourceImpl extends AbstractComponentAttributeSourceImpl
JaxbComponentElement componentElement,
AttributeSourceContainer parentContainer,
String logicalTableName,
NaturalIdMutability naturalIdMutability) {
SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument, componentElement, parentContainer, logicalTableName, naturalIdMutability );
}

View File

@ -40,6 +40,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbCacheElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbMetaElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbNaturalIdCacheElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbParamElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement;
@ -66,6 +67,7 @@ import org.hibernate.metamodel.spi.source.TableSpecificationSource;
* @author Gail Badner
*/
public class Helper {
private static final String NATURAL_ID_CACHE_SUFFIX = "##NaturalId";
public static final ExplicitHibernateTypeSource TO_ONE_ATTRIBUTE_TYPE_SOURCE = new ExplicitHibernateTypeSource() {
@Override
public String getName() {
@ -126,20 +128,39 @@ public class Helper {
: qualifyIfNeeded( entityElement.getName(), unqualifiedClassPackage );
}
public static Value<Caching> createCachingHolder(final JaxbCacheElement cacheElement, final String defaultRegionName) {
public static Caching createCaching(final JaxbCacheElement cacheElement, final String defaultRegionName) {
if ( cacheElement == null ) {
return null;
}
final String region = cacheElement.getRegion() != null ? cacheElement.getRegion() : defaultRegionName;
final AccessType accessType = AccessType.fromExternalName( cacheElement.getUsage() );
final boolean cacheLazyProps = !"non-lazy".equals( cacheElement.getInclude() );
return new Caching( region, accessType, cacheLazyProps );
}
public static Value<Caching> createNaturalIdCachingHolder(final JaxbNaturalIdCacheElement cacheElement, final String entityName, final Caching entityCache) {
return new Value<Caching>(
new Value.DeferredInitializer<Caching>() {
@Override
public Caching initialize() {
if ( cacheElement == null ) {
return null;
new Value.DeferredInitializer<Caching>() {
@Override
public Caching initialize() {
if ( cacheElement == null ) {
return null;
}
final String region;
if ( StringHelper.isEmpty( cacheElement.getRegion() ) ) {
if ( entityCache != null ) {
region = entityCache.getRegion() + NATURAL_ID_CACHE_SUFFIX;
}
else {
region = entityName + NATURAL_ID_CACHE_SUFFIX;
}
}
else {
region = cacheElement.getRegion();
}
return new Caching( region, null, false );
}
final String region = cacheElement.getRegion() != null ? cacheElement.getRegion() : defaultRegionName;
final AccessType accessType = AccessType.fromExternalName( cacheElement.getUsage() );
final boolean cacheLazyProps = !"non-lazy".equals( cacheElement.getInclude() );
return new Caching( region, accessType, cacheLazyProps );
}
}
);
}

View File

@ -31,6 +31,7 @@ import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbManyToOneElement;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.relational.Value;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MappingException;
@ -46,14 +47,14 @@ import org.hibernate.metamodel.spi.source.ToOneAttributeSource;
*/
class ManyToOneAttributeSourceImpl extends AbstractHbmSourceNode implements ToOneAttributeSource {
private final JaxbManyToOneElement manyToOneElement;
private final NaturalIdMutability naturalIdMutability;
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
private final List<RelationalValueSource> valueSources;
ManyToOneAttributeSourceImpl(
MappingDocument sourceMappingDocument,
final JaxbManyToOneElement manyToOneElement,
final String logicalTableName,
NaturalIdMutability naturalIdMutability) {
SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.manyToOneElement = manyToOneElement;
this.naturalIdMutability = naturalIdMutability;
@ -119,7 +120,7 @@ class ManyToOneAttributeSourceImpl extends AbstractHbmSourceNode implements ToOn
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}

View File

@ -28,6 +28,7 @@ import java.util.Map;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbPropertyElement;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -43,13 +44,13 @@ class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements Singu
private final JaxbPropertyElement propertyElement;
private final ExplicitHibernateTypeSource typeSource;
private final List<RelationalValueSource> valueSources;
private final NaturalIdMutability naturalIdMutability;
private final SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
PropertyAttributeSourceImpl(
MappingDocument sourceMappingDocument,
final JaxbPropertyElement propertyElement,
final String logicalTableName,
NaturalIdMutability naturalIdMutability) {
SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.propertyElement = propertyElement;
this.typeSource = new ExplicitHibernateTypeSource() {
@ -135,7 +136,7 @@ class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements Singu
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}

View File

@ -43,6 +43,7 @@ import org.hibernate.internal.util.Value;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.Caching;
import org.hibernate.metamodel.spi.binding.IdGenerator;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.spi.source.AttributeSource;
import org.hibernate.metamodel.spi.source.ComponentAttributeSource;
@ -64,14 +65,20 @@ import org.hibernate.metamodel.spi.source.VersionAttributeSource;
*/
public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements RootEntitySource {
private final TableSpecificationSource primaryTable;
private final Value<Caching> cachingHolder;
private final Caching caching;
private final Value<Caching> naturalIdCachingHolder;
protected RootEntitySourceImpl(
MappingDocument sourceMappingDocument,
JaxbHibernateMapping.JaxbClass entityElement) {
super( sourceMappingDocument, entityElement );
this.primaryTable = Helper.createTableSource( sourceMappingDocument(), entityElement, this );
this.cachingHolder = Helper.createCachingHolder( entityElement().getCache(), getEntityName() );
this.caching = Helper.createCaching( entityElement().getCache(), getEntityName() );
this.naturalIdCachingHolder = Helper.createNaturalIdCachingHolder(
entityElement.getNaturalIdCache(),
getEntityName(),
caching
);
afterInstantiation();
}
@ -131,8 +138,8 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
naturalId.getPropertyOrManyToOneOrComponent(),
null,
naturalId.isMutable()
? SingularAttributeSource.NaturalIdMutability.MUTABLE
: SingularAttributeSource.NaturalIdMutability.IMMUTABLE
? SingularAttributeBinding.NaturalIdMutability.MUTABLE
: SingularAttributeBinding.NaturalIdMutability.IMMUTABLE
);
}
return super.buildAttributeSources( attributeSources );
@ -179,7 +186,12 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
@Override
public Caching getCaching() {
return cachingHolder.getValue();
return caching;
}
@Override
public Caching getNaturalIdCaching() {
return naturalIdCachingHolder.getValue();
}
@Override
@ -417,7 +429,7 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
entityElement().getCompositeId(),
RootEntitySourceImpl.this,
null,
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID
);
}
@ -523,7 +535,7 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
final AttributeSource attributeSource = buildAttributeSource(
attributeElement,
null,
SingularAttributeSource.NaturalIdMutability.NOT_NATURAL_ID
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID
);
if ( ! attributeSource.isSingular() ) {
throw new HibernateException( "Only singular attributes are supported for composite identifiers" );

View File

@ -28,7 +28,7 @@ import java.util.Map;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -142,8 +142,8 @@ class SingularIdentifierAttributeSourceImpl
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return NaturalIdMutability.NOT_NATURAL_ID;
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
@Override

View File

@ -29,6 +29,7 @@ import java.util.Map;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping;
import org.hibernate.internal.util.Value;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -141,8 +142,8 @@ class TimestampAttributeSourceImpl
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return NaturalIdMutability.NOT_NATURAL_ID;
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
@Override

View File

@ -29,6 +29,7 @@ import java.util.Map;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping;
import org.hibernate.internal.util.Value;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource;
@ -147,8 +148,8 @@ class VersionAttributeSourceImpl
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return NaturalIdMutability.NOT_NATURAL_ID;
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability() {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
@Override

View File

@ -36,6 +36,7 @@ public abstract class AbstractSingularAttributeBinding
implements SingularAttributeBinding {
private final boolean isLazy;
private final NaturalIdMutability naturalIdMutability;
protected AbstractSingularAttributeBinding(
AttributeBindingContainer container,
@ -43,9 +44,11 @@ public abstract class AbstractSingularAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean isLazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext) {
super( container, attribute, propertyAccessorName, includedInOptimisticLocking, metaAttributeContext );
this.isLazy = isLazy;
this.naturalIdMutability = naturalIdMutability;
}
protected static boolean hasNullableRelationalValueBinding(List<RelationalValueBinding> relationalValueBindings) {
@ -67,5 +70,10 @@ public abstract class AbstractSingularAttributeBinding
return isLazy;
}
@Override
public NaturalIdMutability getNaturalIdMutability() {
return naturalIdMutability;
}
protected abstract void collectRelationalValueBindings(List<RelationalValueBinding> valueBindings);
}

View File

@ -97,6 +97,7 @@ public interface AttributeBindingContainer {
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
PropertyGeneration generation);
@ -118,6 +119,7 @@ public interface AttributeBindingContainer {
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext);
/**
@ -139,6 +141,7 @@ public interface AttributeBindingContainer {
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
SingularAttributeBinding referencedAttributeBinding,
List<RelationalValueBinding> valueBindings);

View File

@ -33,9 +33,7 @@ import org.hibernate.metamodel.spi.relational.Column;
/**
* @author Gail Badner
*/
public class BackRefAttributeBinding
extends BasicAttributeBinding
implements SingularNonAssociationAttributeBinding {
public class BackRefAttributeBinding extends BasicAttributeBinding {
PluralAttributeBinding pluralAttributeBinding;
@ -50,6 +48,7 @@ public class BackRefAttributeBinding
null,
false,
false,
NaturalIdMutability.NOT_NATURAL_ID,
null,
PropertyGeneration.NEVER
);

View File

@ -58,6 +58,7 @@ public class BasicAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
PropertyGeneration generation) {
super(
@ -66,6 +67,7 @@ public class BasicAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext
);
this.relationalValueBindings = Collections.unmodifiableList( relationalValueBindings );

View File

@ -56,6 +56,7 @@ public class CompositeAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
SingularAttribute parentReference) {
this(
@ -64,6 +65,7 @@ public class CompositeAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
parentReference,
null
@ -74,6 +76,7 @@ public class CompositeAttributeBinding
AttributeBindingContainer container,
SingularAttribute attribute,
String propertyAccessorName,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
List<SingularAttributeBinding> subAttributeBindings) {
this(
@ -82,6 +85,7 @@ public class CompositeAttributeBinding
propertyAccessorName,
false,
false,
naturalIdMutability,
metaAttributeContext,
null,
subAttributeBindings
@ -94,6 +98,7 @@ public class CompositeAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
SingularAttribute parentReference,
List<SingularAttributeBinding> subAttributeBindings) {
@ -103,6 +108,7 @@ public class CompositeAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext
);
@ -211,6 +217,7 @@ public class CompositeAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
PropertyGeneration generation) {
final BasicAttributeBinding binding = new BasicAttributeBinding(
@ -220,6 +227,7 @@ public class CompositeAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
generation
);
@ -239,6 +247,7 @@ public class CompositeAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext) {
final CompositeAttributeBinding binding = new CompositeAttributeBinding(
this,
@ -246,6 +255,7 @@ public class CompositeAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
parentReferenceAttribute
);
@ -259,6 +269,7 @@ public class CompositeAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
SingularAttributeBinding referencedAttributeBinding,
List<RelationalValueBinding> valueBindings) {
@ -268,6 +279,7 @@ public class CompositeAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
referencedAttributeBinding,
valueBindings

View File

@ -490,6 +490,7 @@ public class EntityBinding implements AttributeBindingContainer {
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
PropertyGeneration generation) {
final BasicAttributeBinding binding = new BasicAttributeBinding(
@ -499,6 +500,7 @@ public class EntityBinding implements AttributeBindingContainer {
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
generation
);
@ -513,6 +515,7 @@ public class EntityBinding implements AttributeBindingContainer {
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext) {
final CompositeAttributeBinding binding = new CompositeAttributeBinding(
this,
@ -520,6 +523,7 @@ public class EntityBinding implements AttributeBindingContainer {
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
parentReferenceAttribute
);
@ -540,6 +544,7 @@ public class EntityBinding implements AttributeBindingContainer {
this,
syntheticAttribute,
PropertyAccessorFactory.EMBEDDED_ACCESSOR_NAME,
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID,
metaAttributeContext,
subAttributeBindings
);
@ -570,6 +575,7 @@ public class EntityBinding implements AttributeBindingContainer {
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
SingularAttributeBinding referencedAttributeBinding,
List<RelationalValueBinding> valueBindings) {
@ -579,6 +585,7 @@ public class EntityBinding implements AttributeBindingContainer {
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext,
referencedAttributeBinding,
valueBindings

View File

@ -42,6 +42,7 @@ public class HierarchyDetails {
private EntityVersion entityVersion;
private Caching caching;
private Caching naturalIdCaching;
private boolean explicitPolymorphism;
@ -106,6 +107,14 @@ public class HierarchyDetails {
this.caching = caching;
}
public Caching getNaturalIdCaching() {
return naturalIdCaching;
}
public void setNaturalIdCaching(Caching naturalIdCaching) {
this.naturalIdCaching = naturalIdCaching;
}
public boolean isExplicitPolymorphism() {
return explicitPolymorphism;
}

View File

@ -58,6 +58,7 @@ public class ManyToOneAttributeBinding
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
SingularAttributeBinding referencedAttributeBinding,
List<RelationalValueBinding> relationalValueBindings) {
@ -67,6 +68,7 @@ public class ManyToOneAttributeBinding
propertyAccessorName,
includedInOptimisticLocking,
lazy,
naturalIdMutability,
metaAttributeContext
);

View File

@ -53,4 +53,18 @@ public interface SingularAttributeBinding extends AttributeBinding {
* @return {@code true} indicates that all values allow {@code null}; {@code false} indicates one or more do not
*/
public boolean isNullable();
/**
* Convenience method to determine if this attribute is an natural id and if it is, then returns its mutability.
*
* @return The {@link NaturalIdMutability} linked with this attribute,
* {@code NaturalIdMutability#NOT_NATURAL_ID} indicates this is <b>NOT</b> a natural id attribute.
*/
public NaturalIdMutability getNaturalIdMutability();
public enum NaturalIdMutability {
MUTABLE,
IMMUTABLE,
NOT_NATURAL_ID
}
}

View File

@ -114,4 +114,11 @@ public interface RootEntitySource extends EntitySource {
* @return The caching configuration.
*/
public Caching getCaching();
/**
* Obtain the natural id caching configuration for this entity.
*
* @return The natural id caching configuration.
*/
public Caching getNaturalIdCaching();
}

View File

@ -24,6 +24,7 @@
package org.hibernate.metamodel.spi.source;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
/**
* Source-agnostic description of information needed to bind a singular attribute.
@ -65,11 +66,6 @@ public interface SingularAttributeSource extends AttributeSource, RelationalValu
*
* @return The mutability, see enum for meanings
*/
public NaturalIdMutability getNaturalIdMutability();
public SingularAttributeBinding.NaturalIdMutability getNaturalIdMutability();
public static enum NaturalIdMutability {
MUTABLE,
IMMUTABLE,
NOT_NATURAL_ID
}
}

View File

@ -447,15 +447,15 @@ public class EntityMetamodel implements Serializable {
else {
properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, instrumentationMetadata.isInstrumented() );
}
// TODO: fix when natural IDs are added (HHH-6354)
//if ( attributeBinding.isNaturalIdentifier() ) {
// naturalIdNumbers.add( i );
// if ( attributeBinding.isUpdateable() ) {
// foundUpdateableNaturalIdProperty = true;
// }
//}
if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ){
SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class.cast( attributeBinding );
if(singularAttributeBinding.getNaturalIdMutability() == SingularAttributeBinding.NaturalIdMutability.MUTABLE){
naturalIdNumbers.add( i );
foundUpdateableNaturalIdProperty = true;
} else if(singularAttributeBinding.getNaturalIdMutability() == SingularAttributeBinding.NaturalIdMutability.IMMUTABLE){
naturalIdNumbers.add( i );
}
}
if ( "id".equals( attributeBinding.getAttribute().getName() ) ) {
foundNonIdentifierPropertyNamedId = true;
}
@ -508,7 +508,7 @@ public class EntityMetamodel implements Serializable {
i++;
}
if (naturalIdNumbers.size()==0) {
if (naturalIdNumbers.isEmpty()) {
naturalIdPropertyNumbers = null;
hasImmutableNaturalId = false;
hasCacheableNaturalId = false;
@ -516,7 +516,7 @@ public class EntityMetamodel implements Serializable {
else {
naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers);
hasImmutableNaturalId = !foundUpdateableNaturalIdProperty;
hasCacheableNaturalId = false; //See previous TODO and HHH-6354
hasCacheableNaturalId = entityBinding.getHierarchyDetails().getNaturalIdCaching() != null;
}
hasInsertGeneratedValues = foundInsertGeneratedValue;

View File

@ -36,6 +36,7 @@ import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingCont
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContextImpl;
import org.hibernate.metamodel.internal.source.annotations.EntityHierarchyBuilder;
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableHierarchy;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.source.EntityHierarchy;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.service.classloading.spi.ClassLoaderService;
@ -66,13 +67,14 @@ public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase {
return EntityHierarchyBuilder.createEntityHierarchies( context );
}
public EmbeddableHierarchy createEmbeddableHierarchy(AccessType accessType, Class<?>... configuredClasses) {
public EmbeddableHierarchy createEmbeddableHierarchy(AccessType accessType,SingularAttributeBinding.NaturalIdMutability naturalIdMutability, Class<?>... configuredClasses) {
Index index = JandexHelper.indexForClass(
meta.getServiceRegistry().getService( ClassLoaderService.class ),
configuredClasses
);
AnnotationBindingContext context = new AnnotationBindingContextImpl( meta, index );
return EmbeddableHierarchy.createEmbeddableHierarchy( configuredClasses[0], "", accessType, context );
return EmbeddableHierarchy.createEmbeddableHierarchy( configuredClasses[0], "", accessType,
naturalIdMutability, context );
}
}

View File

@ -38,6 +38,7 @@ import org.junit.Test;
import org.hibernate.AssertionFailure;
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableClass;
import org.hibernate.metamodel.internal.source.annotations.entity.EmbeddableHierarchy;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@ -65,7 +66,7 @@ public class EmbeddableHierarchyTest extends BaseAnnotationIndexTestCase {
}
EmbeddableHierarchy hierarchy = createEmbeddableHierarchy(
AccessType.FIELD,
AccessType.FIELD, SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID,
C.class,
A.class,
B.class
@ -86,7 +87,8 @@ public class EmbeddableHierarchyTest extends BaseAnnotationIndexTestCase {
class NonAnnotatedEmbeddable {
}
createEmbeddableHierarchy( AccessType.FIELD, NonAnnotatedEmbeddable.class );
createEmbeddableHierarchy( AccessType.FIELD,
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID, NonAnnotatedEmbeddable.class );
}
@Entity

View File

@ -86,6 +86,7 @@ public class SimpleValueBindingTests extends BaseUnitTestCase {
"property",
true,
false,
SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID,
null,
PropertyGeneration.NEVER
);