From eb766cc0f77adcf56625625890dcd8bd00a93081 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Thu, 4 Aug 2011 16:06:52 +0200 Subject: [PATCH] HHH-6537 Getting AssociationAttribute into shape. Parsing more association attributes and implementing missing attributes in ToOneAttributeSourceImpl. Preperation for adding @MapsId --- ...nHelper.java => EnumConversionHelper.java} | 69 +++++++- .../source/annotations/JandexHelper.java | 21 ++- .../attribute/AssociationAttribute.java | 158 ++++++++++++++++-- ...ttributeType.java => AttributeNature.java} | 8 +- .../annotations/attribute/BasicAttribute.java | 65 +------ .../attribute/ColumnSourceImpl.java | 29 +++- .../attribute/MappedAttribute.java | 75 ++++++++- .../SingularAttributeSourceImpl.java | 7 +- .../attribute/ToOneAttributeSourceImpl.java | 14 +- .../annotations/entity/ConfiguredClass.java | 39 ++--- .../annotations/entity/EntityClass.java | 4 +- .../annotations/global/IdGeneratorBinder.java | 6 +- .../metamodel/source/binder/ColumnSource.java | 1 + 13 files changed, 366 insertions(+), 130 deletions(-) rename hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/{TypeEnumConversionHelper.java => EnumConversionHelper.java} (50%) rename hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/{AttributeType.java => AttributeNature.java} (92%) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/TypeEnumConversionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java similarity index 50% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/TypeEnumConversionHelper.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java index 92a62e3b83..b8f8b7da4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/TypeEnumConversionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EnumConversionHelper.java @@ -23,18 +23,25 @@ */ package org.hibernate.metamodel.source.annotations; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.GenerationType; import org.hibernate.AssertionFailure; +import org.hibernate.FetchMode; +import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.id.MultipleHiLoPerTableGenerator; +import org.hibernate.internal.util.collections.CollectionHelper; /** - * Helper class which converts type enums from JPA annotations into the Hibernate specific form + * Helper class which converts between different enum types. * * @author Hardy Ferentschik */ -public class TypeEnumConversionHelper { - private TypeEnumConversionHelper() { +public class EnumConversionHelper { + private EnumConversionHelper() { } public static String generationTypeToGeneratorStrategyName(GenerationType generatorEnum, boolean useNewGeneratorMappings) { @@ -56,6 +63,62 @@ public class TypeEnumConversionHelper { } throw new AssertionFailure( "Unknown GeneratorType: " + generatorEnum ); } + + public static CascadeStyle cascadeTypeToCascadeStyle(CascadeType cascadeType) { + switch ( cascadeType ) { + case ALL: { + return CascadeStyle.ALL; + } + case PERSIST: { + return CascadeStyle.PERSIST; + } + case MERGE: { + return CascadeStyle.MERGE; + } + case REMOVE: { + return CascadeStyle.DELETE; + } + case REFRESH: { + return CascadeStyle.REFRESH; + } + case DETACH: { + return CascadeStyle.EVICT; + } + default: { + throw new AssertionFailure( "Unknown cascade type" ); + } + } + } + + public static FetchMode annotationFetchModeToHibernateFetchMode(org.hibernate.annotations.FetchMode annotationFetchMode) { + switch ( annotationFetchMode ) { + case JOIN: { + return FetchMode.JOIN; + } + case SELECT: { + return FetchMode.SELECT; + } + case SUBSELECT: { + // todo - is this correct? can the conversion be made w/o any additional information, eg + // todo - association nature + return FetchMode.SELECT; + } + default: { + throw new AssertionFailure( "Unknown fetch mode" ); + } + } + } + + public static Set cascadeTypeToCascadeStyleSet(Set cascadeTypes) { + if ( CollectionHelper.isEmpty( cascadeTypes ) ) { + return Collections.emptySet(); + } + Set cascadeStyleSet = new HashSet(); + for ( CascadeType cascadeType : cascadeTypes ) { + cascadeStyleSet.add( cascadeTypeToCascadeStyle( cascadeType ) ); + } + return cascadeStyleSet; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java index 8a8dd67811..6f7eca24a6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java @@ -55,6 +55,9 @@ import org.hibernate.service.classloading.spi.ClassLoaderService; public class JandexHelper { private static final Map DEFAULT_VALUES_BY_ELEMENT = new HashMap(); + private JandexHelper() { + } + /** * Retrieves a jandex annotation element value. If the value is {@code null}, the default value specified in the * annotation class is retrieved instead. @@ -212,6 +215,19 @@ public class JandexHelper { } } + /** + * @param annotations List of annotation instances keyed against their dot name. + * @param annotationName the annotation to check + * + * @return returns {@code true} if the map contains only a single instance of specified annotation or {@code false} otherwise. + * + * @throws org.hibernate.AssertionFailure in case there is there is more than one annotation of this type. + */ + public static boolean containsSingleAnnotations(Map> annotations, DotName annotationName) + throws AssertionFailure { + return getSingleAnnotation( annotations, annotationName ) != null; + } + /** * Creates a jandex index for the specified classes * @@ -274,7 +290,7 @@ public class JandexHelper { return annotations; } - public static void addAnnotationToMap(AnnotationInstance instance, Map> annotations) { + private static void addAnnotationToMap(AnnotationInstance instance, Map> annotations) { DotName dotName = instance.name(); List list; if ( annotations.containsKey( dotName ) ) { @@ -287,9 +303,6 @@ public class JandexHelper { list.add( instance ); } - private JandexHelper() { - } - private static Object getDefaultValue(AnnotationInstance annotation, String element) { String name = annotation.name().toString(); String fqElement = name + '.' + element; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java index 51af34b508..1be88bd86b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AssociationAttribute.java @@ -28,42 +28,67 @@ import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.CascadeType; +import javax.persistence.FetchType; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.DotName; +import org.hibernate.FetchMode; import org.hibernate.annotations.NotFoundAction; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.source.annotations.HibernateDotNames; import org.hibernate.metamodel.source.annotations.JandexHelper; +import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; +import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolverImpl; +import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver; /** + * Represents an association attribute. + * * @author Hardy Ferentschik + * @todo Check whether we need further subclasses for different association types. Needs to evolve during development (HF) */ -public class AssociationAttribute extends BasicAttribute { - private final AttributeType associationType; +public class AssociationAttribute extends MappedAttribute { + private final AttributeNature associationNature; private final boolean ignoreNotFound; private final String referencedEntityType; + private final String mappedBy; private final Set cascadeTypes; + private final boolean isOptional; + private final boolean isLazy; + private final boolean isOrphanRemoval; + private final FetchMode fetchMode; + + private boolean isInsertable = true; + private boolean isUpdatable = true; + private AttributeTypeResolver resolver; public static AssociationAttribute createAssociationAttribute(String name, Class attributeType, - AttributeType attributeNature, + AttributeNature attributeNature, String accessType, Map> annotations, AnnotationBindingContext context) { - return new AssociationAttribute( name, attributeType, attributeNature, accessType, annotations, context ); + return new AssociationAttribute( + name, + attributeType, + attributeNature, + accessType, + annotations, + context + ); } private AssociationAttribute(String name, Class javaType, - AttributeType associationType, + AttributeNature associationType, String accessType, Map> annotations, AnnotationBindingContext context) { super( name, javaType, accessType, annotations, context ); - this.associationType = associationType; + this.associationNature = associationType; this.ignoreNotFound = ignoreNotFound(); AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation( @@ -71,8 +96,15 @@ public class AssociationAttribute extends BasicAttribute { associationType.getAnnotationDotName() ); - referencedEntityType = determineReferencedEntityType( associationAnnotation ); - cascadeTypes = determineCascadeTypes( associationAnnotation ); + // using jandex we don't really care which exact type of annotation we are dealing with + this.referencedEntityType = determineReferencedEntityType( associationAnnotation ); + this.mappedBy = determineMappedByAttributeName( associationAnnotation ); + this.isOptional = determineOptionality( associationAnnotation ); + this.isLazy = determineFetchType( associationAnnotation ); + this.isOrphanRemoval = determineOrphanRemoval( associationAnnotation ); + this.cascadeTypes = determineCascadeTypes( associationAnnotation ); + + this.fetchMode = determineFetchMode(); } public boolean isIgnoreNotFound() { @@ -83,14 +115,63 @@ public class AssociationAttribute extends BasicAttribute { return referencedEntityType; } - public AttributeType getAssociationType() { - return associationType; + public String getMappedBy() { + return mappedBy; + } + + public AttributeNature getAssociationNature() { + return associationNature; } public Set getCascadeTypes() { return cascadeTypes; } + public boolean isOrphanRemoval() { + return isOrphanRemoval; + } + + public FetchMode getFetchMode() { + return fetchMode; + } + + @Override + public AttributeTypeResolver getHibernateTypeResolver() { + if ( resolver == null ) { + resolver = getDefaultHibernateTypeResolver(); + } + return resolver; + } + + @Override + public boolean isLazy() { + return isLazy; + } + + @Override + public boolean isOptional() { + return isOptional; + } + + @Override + public boolean isInsertable() { + return isInsertable; + } + + @Override + public boolean isUpdatable() { + return isUpdatable; + } + + @Override + public PropertyGeneration getPropertyGeneration() { + return PropertyGeneration.NEVER; + } + + private AttributeTypeResolver getDefaultHibernateTypeResolver() { + return new CompositeAttributeTypeResolver( new AttributeTypeResolverImpl( this ) ); + } + private boolean ignoreNotFound() { NotFoundAction action = NotFoundAction.EXCEPTION; AnnotationInstance notFoundAnnotation = JandexHelper.getSingleAnnotation( @@ -107,6 +188,38 @@ public class AssociationAttribute extends BasicAttribute { return NotFoundAction.IGNORE.equals( action ); } + private boolean determineOptionality(AnnotationInstance associationAnnotation) { + boolean optional = true; + + AnnotationValue optionalValue = associationAnnotation.value( "optional" ); + if ( optionalValue != null ) { + optional = optionalValue.asBoolean(); + } + + return optional; + } + + private boolean determineOrphanRemoval(AnnotationInstance associationAnnotation) { + boolean orphanRemoval = false; + AnnotationValue orphanRemovalValue = associationAnnotation.value( "orphanRemoval" ); + if ( orphanRemovalValue != null ) { + orphanRemoval = orphanRemovalValue.asBoolean(); + } + return orphanRemoval; + } + + private boolean determineFetchType(AnnotationInstance associationAnnotation) { + boolean lazy = false; + AnnotationValue fetchValue = associationAnnotation.value( "fetch" ); + if ( fetchValue != null ) { + FetchType fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() ); + if ( FetchType.LAZY.equals( fetchType ) ) { + lazy = true; + } + } + return lazy; + } + private String determineReferencedEntityType(AnnotationInstance associationAnnotation) { String targetTypeName = getAttributeType().getName(); @@ -126,6 +239,16 @@ public class AssociationAttribute extends BasicAttribute { return targetTypeName; } + private String determineMappedByAttributeName(AnnotationInstance associationAnnotation) { + String mappedBy = null; + AnnotationValue mappedByAnnotationValue = associationAnnotation.value( "mappedBy" ); + if ( mappedByAnnotationValue != null ) { + mappedBy = mappedByAnnotationValue.asString(); + } + + return mappedBy; + } + private Set determineCascadeTypes(AnnotationInstance associationAnnotation) { Set cascadeTypes = new HashSet(); AnnotationValue cascadeValue = associationAnnotation.value( "cascade" ); @@ -137,6 +260,21 @@ public class AssociationAttribute extends BasicAttribute { } return cascadeTypes; } + + private FetchMode determineFetchMode() { + FetchMode mode = FetchMode.DEFAULT; + + AnnotationInstance fetchAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.FETCH ); + if ( fetchAnnotation != null ) { + org.hibernate.annotations.FetchMode annotationFetchMode = JandexHelper.getEnumValue( + fetchAnnotation, + "value", + org.hibernate.annotations.FetchMode.class + ); + } + + return mode; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java index 58dff71a6e..084660cfd2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeNature.java @@ -32,19 +32,19 @@ import org.hibernate.metamodel.source.annotations.JPADotNames; * * @author Hardy Ferentschik */ -public enum AttributeType { - BASIC( null ), +public enum AttributeNature { + BASIC( JPADotNames.BASIC ), ONE_TO_ONE( JPADotNames.ONE_TO_ONE ), ONE_TO_MANY( JPADotNames.ONE_TO_MANY ), MANY_TO_ONE( JPADotNames.MANY_TO_ONE ), MANY_TO_MANY( JPADotNames.MANY_TO_MANY ), ELEMENT_COLLECTION( JPADotNames.ELEMENT_COLLECTION ), - EMBEDDED_ID( JPADotNames.EMBEDDED_ID ), + EMBEDDED_ID( JPADotNames.EMBEDDED_ID ), EMBEDDED( JPADotNames.EMBEDDED ); private final DotName annotationDotName; - AttributeType(DotName annotationDotName) { + AttributeNature(DotName annotationDotName) { this.annotationDotName = annotationDotName; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java index 8e57deb179..f9e03ae780 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/BasicAttribute.java @@ -44,7 +44,7 @@ import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.source.annotations.HibernateDotNames; import org.hibernate.metamodel.source.annotations.JPADotNames; import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.TypeEnumConversionHelper; +import org.hibernate.metamodel.source.annotations.EnumConversionHelper; import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; import org.hibernate.metamodel.source.annotations.attribute.type.CompositeAttributeTypeResolver; import org.hibernate.metamodel.source.annotations.attribute.type.EnumeratedTypeResolver; @@ -53,15 +53,11 @@ import org.hibernate.metamodel.source.annotations.attribute.type.LobTypeResolver import org.hibernate.metamodel.source.annotations.attribute.type.TemporalTypeResolver; /** - * Represent a mapped attribute (explicitly or implicitly mapped). + * Represent a basic attribute (explicitly or implicitly mapped). * * @author Hardy Ferentschik */ public class BasicAttribute extends MappedAttribute { - /** - * Is this property an id property (or part thereof). - */ - private final boolean isId; /** * The id generator in case this basic attribute represents an simple id. Will be {@code null} in case there @@ -74,12 +70,6 @@ public class BasicAttribute extends MappedAttribute { */ private final boolean isVersioned; - /** - * Whether a change of the property's value triggers a version increment of the entity (in case of optimistic - * locking). - */ - private final boolean isOptimisticLockable; - /** * Is this property lazy loaded (see {@link javax.persistence.Basic}). */ @@ -97,11 +87,6 @@ public class BasicAttribute extends MappedAttribute { private boolean isInsertable = true; private boolean isUpdatable = true; - /** - * Defines the column values (relational values) for this property. - */ - private ColumnValues columnValues; - private final String customWriteFragment; private final String customReadFragment; private final String checkCondition; @@ -122,32 +107,19 @@ public class BasicAttribute extends MappedAttribute { AnnotationBindingContext context) { super( name, attributeType, accessType, annotations, context ); - AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); - AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation( - annotations, - JPADotNames.EMBEDDED_ID - ); - //if this attribute has either @Id or @EmbeddedId, then it is an id attribute - isId = ( idAnnotation != null || embeddedIdAnnotation != null ); - AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION ); isVersioned = versionAnnotation != null; - AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.COLUMN ); - columnValues = new ColumnValues( columnAnnotation ); - - if ( isId ) { + if ( isId() ) { // an id must be unique and cannot be nullable - columnValues.setUnique( true ); - columnValues.setNullable( false ); + getColumnValues().setUnique( true ); + getColumnValues().setNullable( false ); idGenerator = checkGeneratedValueAnnotation(); } else { idGenerator = null; } - this.isOptimisticLockable = checkOptimisticLockAnnotation(); - checkBasicAnnotation(); checkGeneratedAnnotation(); @@ -158,14 +130,6 @@ public class BasicAttribute extends MappedAttribute { this.checkCondition = parseCheckAnnotation(); } - public final ColumnValues getColumnValues() { - return columnValues; - } - - public boolean isId() { - return isId; - } - public boolean isVersioned() { return isVersioned; } @@ -190,10 +154,6 @@ public class BasicAttribute extends MappedAttribute { return propertyGeneration; } - public boolean isOptimisticLockable() { - return isOptimisticLockable; - } - public String getCustomWriteFragment() { return customWriteFragment; } @@ -218,19 +178,6 @@ public class BasicAttribute extends MappedAttribute { return sb.toString(); } - private boolean checkOptimisticLockAnnotation() { - boolean triggersVersionIncrement = true; - AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( - annotations(), - HibernateDotNames.OPTIMISTIC_LOCK - ); - if ( optimisticLockAnnotation != null ) { - boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean(); - triggersVersionIncrement = !exclude; - } - return triggersVersionIncrement; - } - private void checkBasicAnnotation() { AnnotationInstance basicAnnotation = JandexHelper.getSingleAnnotation( annotations(), JPADotNames.BASIC ); if ( basicAnnotation != null ) { @@ -346,7 +293,7 @@ public class BasicAttribute extends MappedAttribute { "strategy", GenerationType.class ); - String strategy = TypeEnumConversionHelper.generationTypeToGeneratorStrategyName( + String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( genType, getContext().getMetadataImplementor().getOptions().useNewIdentifierGenerators() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java index 56b124aa8e..232318662e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ColumnSourceImpl.java @@ -29,13 +29,13 @@ import org.hibernate.internal.util.StringHelper; * @author Hardy Ferentschik */ public class ColumnSourceImpl extends ColumnValuesSourceImpl { - private final BasicAttribute attribute; + private final MappedAttribute attribute; private final String name; - ColumnSourceImpl(BasicAttribute attribute, AttributeOverride attributeOverride) { + ColumnSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { super( attribute.getColumnValues() ); - if(attributeOverride != null) { - setOverrideColumnValues( attributeOverride.getColumnValues() ); + if ( attributeOverride != null ) { + setOverrideColumnValues( attributeOverride.getColumnValues() ); } this.attribute = attribute; this.name = resolveColumnName(); @@ -58,17 +58,32 @@ public class ColumnSourceImpl extends ColumnValuesSourceImpl { @Override public String getReadFragment() { - return attribute.getCustomReadFragment(); + if ( attribute instanceof BasicAttribute ) { + return ( (BasicAttribute) attribute ).getCustomReadFragment(); + } + else { + return null; + } } @Override public String getWriteFragment() { - return attribute.getCustomWriteFragment(); + if ( attribute instanceof BasicAttribute ) { + return ( (BasicAttribute) attribute ).getCustomWriteFragment(); + } + else { + return null; + } } @Override public String getCheckCondition() { - return attribute.getCheckCondition(); + if ( attribute instanceof BasicAttribute ) { + return ( (BasicAttribute) attribute ).getCheckCondition(); + } + else { + return null; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java index 6daa25d2f5..477ba00f4c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/MappedAttribute.java @@ -29,7 +29,11 @@ import java.util.Map; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; +import org.hibernate.metamodel.source.annotations.HibernateDotNames; +import org.hibernate.metamodel.source.annotations.JPADotNames; +import org.hibernate.metamodel.source.annotations.JandexHelper; import org.hibernate.metamodel.source.annotations.attribute.type.AttributeTypeResolver; /** @@ -59,6 +63,22 @@ public abstract class MappedAttribute implements Comparable { */ private final String accessType; + /** + * Defines the column values (relational values) for this property. + */ + private ColumnValues columnValues; + + /** + * Is this property an id property (or part thereof). + */ + private final boolean isId; + + /** + * Whether a change of the property's value triggers a version increment of the entity (in case of optimistic + * locking). + */ + private final boolean isOptimisticLockable; + /** * The binding context */ @@ -70,6 +90,22 @@ public abstract class MappedAttribute implements Comparable { this.name = name; this.attributeType = attributeType; this.accessType = accessType; + + //if this attribute has either @Id or @EmbeddedId, then it is an id attribute + AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID ); + AnnotationInstance embeddedIdAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.EMBEDDED_ID + ); + isId = ( idAnnotation != null || embeddedIdAnnotation != null ); + + AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( + annotations, + JPADotNames.COLUMN + ); + columnValues = new ColumnValues( columnAnnotation ); + + this.isOptimisticLockable = checkOptimisticLockAnnotation(); } public String getName() { @@ -92,13 +128,23 @@ public abstract class MappedAttribute implements Comparable { return annotations; } + public ColumnValues getColumnValues() { + return columnValues; + } + + public boolean isId() { + return isId; + } + + public boolean isOptimisticLockable() { + return isOptimisticLockable; + } + @Override public int compareTo(MappedAttribute mappedProperty) { return name.compareTo( mappedProperty.getName() ); } - public abstract AttributeTypeResolver getHibernateTypeResolver(); - @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -107,6 +153,31 @@ public abstract class MappedAttribute implements Comparable { sb.append( '}' ); return sb.toString(); } + + public abstract AttributeTypeResolver getHibernateTypeResolver(); + + public abstract boolean isLazy(); + + public abstract boolean isOptional(); + + public abstract boolean isInsertable(); + + public abstract boolean isUpdatable(); + + public abstract PropertyGeneration getPropertyGeneration(); + + private boolean checkOptimisticLockAnnotation() { + boolean triggersVersionIncrement = true; + AnnotationInstance optimisticLockAnnotation = JandexHelper.getSingleAnnotation( + annotations(), + HibernateDotNames.OPTIMISTIC_LOCK + ); + if ( optimisticLockAnnotation != null ) { + boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean(); + triggersVersionIncrement = !exclude; + } + return triggersVersionIncrement; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java index 048df6971e..3b97d0b62c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SingularAttributeSourceImpl.java @@ -38,14 +38,14 @@ import org.hibernate.metamodel.source.binder.SingularAttributeSource; * @author Hardy Ferentschik */ public class SingularAttributeSourceImpl implements SingularAttributeSource { - private final BasicAttribute attribute; + private final MappedAttribute attribute; private final AttributeOverride attributeOverride; - public SingularAttributeSourceImpl(BasicAttribute attribute) { + public SingularAttributeSourceImpl(MappedAttribute attribute) { this(attribute, null); } - public SingularAttributeSourceImpl(BasicAttribute attribute, AttributeOverride attributeOverride) { + public SingularAttributeSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { this.attribute = attribute; this.attributeOverride = attributeOverride; } @@ -117,7 +117,6 @@ public class SingularAttributeSourceImpl implements SingularAttributeSource { return Collections.emptySet(); } - @Override public boolean areValuesIncludedInInsertByDefault() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java index 05c635ac6f..0b5b0294b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/ToOneAttributeSourceImpl.java @@ -23,11 +23,11 @@ */ package org.hibernate.metamodel.source.annotations.attribute; -import java.util.HashSet; import java.util.Set; import org.hibernate.FetchMode; import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.metamodel.source.annotations.EnumConversionHelper; import org.hibernate.metamodel.source.binder.SingularAttributeNature; import org.hibernate.metamodel.source.binder.ToOneAttributeSource; @@ -36,15 +36,12 @@ import org.hibernate.metamodel.source.binder.ToOneAttributeSource; */ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource { private final AssociationAttribute associationAttribute; - private final Set cascadeStyles = new HashSet(); + private final Set cascadeStyles; public ToOneAttributeSourceImpl(AssociationAttribute associationAttribute) { super( associationAttribute ); this.associationAttribute = associationAttribute; - - for ( javax.persistence.CascadeType cascadeType : associationAttribute.getCascadeTypes() ) { - // todo : ... - } + this.cascadeStyles = EnumConversionHelper.cascadeTypeToCascadeStyleSet( associationAttribute.getCascadeTypes() ); } @Override @@ -59,7 +56,7 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem @Override public String getReferencedEntityAttributeName() { - return null; + return associationAttribute.getMappedBy(); } @Override @@ -69,8 +66,7 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem @Override public FetchMode getFetchMode() { - // todo : implement - return FetchMode.DEFAULT; + return associationAttribute.getFetchMode(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java index adad5d2a5a..76884ab551 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/ConfiguredClass.java @@ -61,8 +61,8 @@ import org.hibernate.metamodel.source.annotations.JPADotNames; import org.hibernate.metamodel.source.annotations.JandexHelper; import org.hibernate.metamodel.source.annotations.ReflectionHelper; import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.source.annotations.attribute.AttributeNature; import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; -import org.hibernate.metamodel.source.annotations.attribute.AttributeType; import org.hibernate.metamodel.source.annotations.attribute.BasicAttribute; /** @@ -181,10 +181,6 @@ public class ConfiguredClass { return localBindingContext; } - public ConfiguredClassType getConfiguredClassType() { - return configuredClassType; - } - public Iterable getSimpleAttributes() { return simpleAttributeMap.values(); } @@ -446,7 +442,7 @@ public class ConfiguredClass { classInfo, member.getName() ); - AttributeType attributeNature = determineAttributeType( annotations ); + AttributeNature attributeNature = determineAttributeNature( annotations ); String accessTypeString = accessType.toString().toLowerCase(); switch ( attributeNature ) { case BASIC: { @@ -457,8 +453,7 @@ public class ConfiguredClass { idAttributeMap.put( attributeName, attribute ); } else if ( attribute.isVersioned() ) { - if ( - versionAttribute == null ) { + if ( versionAttribute == null ) { versionAttribute = attribute; } else { @@ -489,7 +484,7 @@ public class ConfiguredClass { resolveEmbeddable( attributeName, attributeType ); break; } - // TODO handle the different association types + // OneToOne, OneToMany, ManyToOne, ManyToMany default: { AssociationAttribute attribute = AssociationAttribute.createAssociationAttribute( attributeName, @@ -534,38 +529,38 @@ public class ConfiguredClass { * * @return an instance of the {@code AttributeType} enum */ - private AttributeType determineAttributeType(Map> annotations) { - EnumMap discoveredAttributeTypes = - new EnumMap( AttributeType.class ); + private AttributeNature determineAttributeNature(Map> annotations) { + EnumMap discoveredAttributeTypes = + new EnumMap( AttributeNature.class ); AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ); if ( oneToOne != null ) { - discoveredAttributeTypes.put( AttributeType.ONE_TO_ONE, oneToOne ); + discoveredAttributeTypes.put( AttributeNature.ONE_TO_ONE, oneToOne ); } AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ); if ( oneToMany != null ) { - discoveredAttributeTypes.put( AttributeType.ONE_TO_MANY, oneToMany ); + discoveredAttributeTypes.put( AttributeNature.ONE_TO_MANY, oneToMany ); } AnnotationInstance manyToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ); if ( manyToOne != null ) { - discoveredAttributeTypes.put( AttributeType.MANY_TO_ONE, manyToOne ); + discoveredAttributeTypes.put( AttributeNature.MANY_TO_ONE, manyToOne ); } AnnotationInstance manyToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ); if ( manyToMany != null ) { - discoveredAttributeTypes.put( AttributeType.MANY_TO_MANY, manyToMany ); + discoveredAttributeTypes.put( AttributeNature.MANY_TO_MANY, manyToMany ); } AnnotationInstance embedded = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED ); if ( embedded != null ) { - discoveredAttributeTypes.put( AttributeType.EMBEDDED, embedded ); + discoveredAttributeTypes.put( AttributeNature.EMBEDDED, embedded ); } - AnnotationInstance embeddIded = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID ); - if ( embeddIded != null ) { - discoveredAttributeTypes.put( AttributeType.EMBEDDED_ID, embeddIded ); + AnnotationInstance embeddedId = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID ); + if ( embeddedId != null ) { + discoveredAttributeTypes.put( AttributeNature.EMBEDDED_ID, embeddedId ); } AnnotationInstance elementCollection = JandexHelper.getSingleAnnotation( @@ -573,11 +568,11 @@ public class ConfiguredClass { JPADotNames.ELEMENT_COLLECTION ); if ( elementCollection != null ) { - discoveredAttributeTypes.put( AttributeType.ELEMENT_COLLECTION, elementCollection ); + discoveredAttributeTypes.put( AttributeNature.ELEMENT_COLLECTION, elementCollection ); } if ( discoveredAttributeTypes.size() == 0 ) { - return AttributeType.BASIC; + return AttributeNature.BASIC; } else if ( discoveredAttributeTypes.size() == 1 ) { return discoveredAttributeTypes.keySet().iterator().next(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java index 4c55b1d0fd..f61adfbd8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java @@ -311,13 +311,11 @@ public class EntityClass extends ConfiguredClass { idAnnotationList.addAll( getClassInfo().annotations().get( idAnnotationType ) ); } ConfiguredClass parent = getParent(); - while ( parent != null && ( ConfiguredClassType.MAPPED_SUPERCLASS.equals( parent.getConfiguredClassType() ) || - ConfiguredClassType.NON_ENTITY.equals( parent.getConfiguredClassType() ) ) ) { + while ( parent != null ) { if ( parent.getClassInfo().annotations().get( idAnnotationType ) != null ) { idAnnotationList.addAll( parent.getClassInfo().annotations().get( idAnnotationType ) ); } parent = parent.getParent(); - } return idAnnotationList; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java index 2406cc41a1..e0d51d184d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/global/IdGeneratorBinder.java @@ -49,7 +49,7 @@ import org.hibernate.metamodel.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.source.annotations.HibernateDotNames; import org.hibernate.metamodel.source.annotations.JPADotNames; import org.hibernate.metamodel.source.annotations.JandexHelper; -import org.hibernate.metamodel.source.annotations.TypeEnumConversionHelper; +import org.hibernate.metamodel.source.annotations.EnumConversionHelper; /** * Binds {@link SequenceGenerator}, {@link javax.persistence.TableGenerator}, {@link GenericGenerator}, and @@ -141,7 +141,7 @@ public class IdGeneratorBinder { Map parameterMap = new HashMap(); addStringParameter( generator, "sequenceName", parameterMap, SequenceStyleGenerator.SEQUENCE_PARAM ); boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); - String strategy = TypeEnumConversionHelper.generationTypeToGeneratorStrategyName( + String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( GenerationType.SEQUENCE, useNewIdentifierGenerators ); @@ -176,7 +176,7 @@ public class IdGeneratorBinder { addStringParameter( generator, "catalog", parameterMap, PersistentIdentifierGenerator.CATALOG ); addStringParameter( generator, "schema", parameterMap, PersistentIdentifierGenerator.SCHEMA ); boolean useNewIdentifierGenerators = metadata.getOptions().useNewIdentifierGenerators(); - String strategy = TypeEnumConversionHelper.generationTypeToGeneratorStrategyName( + String strategy = EnumConversionHelper.generationTypeToGeneratorStrategyName( GenerationType.TABLE, useNewIdentifierGenerators ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java index f33cc18d54..3f86bd6b0f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/ColumnSource.java @@ -110,5 +110,6 @@ public interface ColumnSource extends RelationalValueSource { public String getComment(); public boolean isIncludedInInsert(); + public boolean isIncludedInUpdate(); }