diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java index f2824f080b..2889eda4ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/AttributeOverride.java @@ -44,6 +44,14 @@ public class AttributeOverride { ); } + public ColumnValues getColumnValues() { + return columnValues; + } + + public String getAttributePath() { + return attributePath; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); 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 d3b210384c..a8f66a9248 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 @@ -80,6 +80,10 @@ public abstract class MappedAttribute implements Comparable { return typeParameters; } + public Map> getAnnotations() { + return annotations; + } + /** * Returns the annotation with the specified name or {@code null} * diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java index 75c36f4ac7..bb078ebfb0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/SimpleAttribute.java @@ -84,12 +84,18 @@ public class SimpleAttribute extends MappedAttribute { /** * Defines the column values (relational values) for this property. */ - private final ColumnValues columnValues; + private ColumnValues columnValues; public static SimpleAttribute createSimpleAttribute(String name, String type, Map> annotations) { return new SimpleAttribute( name, type, annotations, false ); } + public static SimpleAttribute createSimpleAttribute(SimpleAttribute simpleAttribute, ColumnValues columnValues) { + SimpleAttribute attribute = new SimpleAttribute( simpleAttribute.getName(), simpleAttribute.getType(), simpleAttribute.getAnnotations(), false ); + attribute.columnValues = columnValues; + return attribute; + } + public static SimpleAttribute createDiscriminatorAttribute(Map> annotations) { AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.DISCRIMINATOR_COLUMN 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 3cfe49a3e3..d2d3b828c2 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 @@ -114,6 +114,12 @@ public class ConfiguredClass { */ private final Map embeddedClasses = new HashMap(); + /** + * A map of all attribute overrides defined in this class. The override name is "normalised", meaning as if specified + * on class level. If the override is specified on attribute level the attribute name is used as prefix. + */ + private final Map attributeOverrideMap; + private final Set transientFieldNames = new HashSet(); private final Set transientMethodNames = new HashSet(); @@ -134,7 +140,7 @@ public class ConfiguredClass { this.associationAttributeMap = new TreeMap(); collectAttributes(); - List attributeOverrideList = findAttributeOverrides(); + attributeOverrideMap = Collections.unmodifiableMap( findAttributeOverrides() ); } public String getName() { @@ -185,6 +191,10 @@ public class ConfiguredClass { return attribute; } + public AttributeOverride geAttributeOverrideForPath(String propertyPath) { + return attributeOverrideMap.get( propertyPath ); + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -533,8 +543,8 @@ public class ConfiguredClass { } } - private List findAttributeOverrides() { - List attributeOverrideList = new ArrayList(); + private Map findAttributeOverrides() { + Map attributeOverrideList = new HashMap(); AnnotationInstance attributeOverrideAnnotation = JandexHelper.getSingleAnnotation( classInfo, @@ -542,7 +552,8 @@ public class ConfiguredClass { ); if ( attributeOverrideAnnotation != null ) { String prefix = createPathPrefix( attributeOverrideAnnotation ); - attributeOverrideList.add( new AttributeOverride( prefix, attributeOverrideAnnotation ) ); + AttributeOverride override = new AttributeOverride( prefix, attributeOverrideAnnotation ); + attributeOverrideList.put( override.getAttributePath(), override ); } AnnotationInstance attributeOverridesAnnotation = JandexHelper.getSingleAnnotation( @@ -553,7 +564,8 @@ public class ConfiguredClass { AnnotationInstance[] annotationInstances = attributeOverridesAnnotation.value().asNestedArray(); for ( AnnotationInstance annotationInstance : annotationInstances ) { String prefix = createPathPrefix( annotationInstance ); - attributeOverrideList.add( new AttributeOverride( prefix, annotationInstance ) ); + AttributeOverride override = new AttributeOverride( prefix, annotationInstance ); + attributeOverrideList.put( override.getAttributePath(), override ); } } return attributeOverrideList; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java index c2bc8e74b4..e0afec63a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java @@ -67,6 +67,7 @@ import org.hibernate.metamodel.relational.UniqueKey; import org.hibernate.metamodel.source.annotations.HibernateDotNames; import org.hibernate.metamodel.source.annotations.JPADotNames; import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute; +import org.hibernate.metamodel.source.annotations.attribute.AttributeOverride; import org.hibernate.metamodel.source.annotations.attribute.MappedAttribute; import org.hibernate.metamodel.source.annotations.attribute.SimpleAttribute; import org.hibernate.metamodel.source.annotations.attribute.state.binding.AttributeBindingStateImpl; @@ -409,7 +410,7 @@ public class EntityBinder { entityClass.getClassInfo(), JPADotNames.TABLE ); if ( tableAnnotation != null ) { - schemaName = JandexHelper.getValue( tableAnnotation, "schema", String.class); + schemaName = JandexHelper.getValue( tableAnnotation, "schema", String.class ); catalogName = JandexHelper.getValue( tableAnnotation, "catalog", String.class ); String explicitTableName = JandexHelper.getValue( tableAnnotation, "name", String.class ); if ( StringHelper.isNotEmpty( explicitTableName ) ) { @@ -614,13 +615,15 @@ public class EntityBinder { private void bindAttributes(EntityBinding entityBinding) { // bind the attributes of this entity AttributeContainer entity = entityBinding.getEntity(); - bindAttributes( entityBinding, entity, entityClass ); + bindAttributes( entityBinding, entity, entityClass, null ); // bind potential mapped super class attributes + ConfiguredClass childClass = entityClass; ConfiguredClass parent = entityClass.getParent(); Hierarchical superTypeContainer = entityBinding.getEntity().getSuperType(); while ( containsPotentialMappedSuperclassAttributes( parent ) ) { - bindAttributes( entityBinding, superTypeContainer, parent ); + bindAttributes( entityBinding, superTypeContainer, parent, childClass ); + childClass = parent; parent = parent.getParent(); superTypeContainer = superTypeContainer.getSuperType(); } @@ -631,8 +634,15 @@ public class EntityBinder { ConfiguredClassType.NON_ENTITY.equals( parent.getConfiguredClassType() ) ); } - private void bindAttributes(EntityBinding entityBinding, AttributeContainer attributeContainer, ConfiguredClass configuredClass) { + private void bindAttributes(EntityBinding entityBinding, AttributeContainer attributeContainer, ConfiguredClass configuredClass, ConfiguredClass childClass) { for ( SimpleAttribute simpleAttribute : configuredClass.getSimpleAttributes() ) { + String attributeName = simpleAttribute.getName(); + + if(childClass != null && childClass.geAttributeOverrideForPath(attributeName) != null) { + AttributeOverride override = childClass.geAttributeOverrideForPath(attributeName); + simpleAttribute = SimpleAttribute.createSimpleAttribute( simpleAttribute, override.getColumnValues() ); + } + bindSingleMappedAttribute( entityBinding, attributeContainer, diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTests.java index 1801b3f88a..1c1f517c12 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/MappedSuperclassTests.java @@ -48,13 +48,12 @@ import static junit.framework.Assert.assertTrue; /** * Tests for {@link javax.persistence.MappedSuperclass} {@link javax.persistence.AttributeOverrides} - * and {@code javax.persistence.AttributeOverride}. + * and {@link javax.persistence.AttributeOverride}. * * @author Hardy Ferentschik */ public class MappedSuperclassTests extends BaseAnnotationBindingTestCase { @Test - @FailureExpected(jiraKey = "HHH-6392", message = "work in progress") public void testMappedSuperclass() { buildMetadataSources( MyMappedSuperClass.class, MyEntity.class, Address.class ); @@ -75,7 +74,7 @@ public class MappedSuperclassTests extends BaseAnnotationBindingTestCase { SimpleValue value = tuple.values().iterator().next(); assertTrue( value instanceof Column ); Column column = (Column) value; - assertEquals( "Wrong column name", "MY_NAME", column.getColumnName().toString() ); + assertEquals( "Wrong column name", "`MY_NAME`", column.getColumnName().toString() ); AttributeBinding idBinding = binding.getEntityIdentifier().getValueBinding(); assertNotNull( "the id attribute should be bound", idBinding );