From 7f1dbc2ef0c6b2f27077f2eea35723c722f07004 Mon Sep 17 00:00:00 2001 From: brmeyer Date: Tue, 16 Oct 2012 13:49:11 -0400 Subject: [PATCH] HHH-7678 Attribute's type is an @Embeddable static class -- incorrectly bound to Basic --- .../hibernate/metamodel/MetadataSources.java | 16 ++++--- .../annotations/entity/ConfiguredClass.java | 47 ++++++++++++++----- .../annotations/access/jpa/AccessTest.java | 24 +++++----- .../annotations/access/jpa/Gardenshed.java | 5 +- .../test/annotations/access/jpa/Square.java | 2 +- .../annotations/beanvalidation/DDLTest.java | 3 +- .../test/annotations/beanvalidation/Tv.java | 1 + 7 files changed, 64 insertions(+), 34 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java index 604815f81d..eec02e7a8f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java @@ -38,14 +38,10 @@ import java.util.Set; import java.util.jar.JarFile; import java.util.zip.ZipEntry; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.Indexer; -import org.jboss.logging.Logger; -import org.w3c.dom.Document; - import org.hibernate.HibernateException; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.CacheRegionDefinition; import org.hibernate.jaxb.internal.JaxbMappingProcessor; import org.hibernate.jaxb.spi.JaxbRoot; @@ -56,8 +52,11 @@ import org.hibernate.metamodel.internal.MetadataBuilderImpl; import org.hibernate.metamodel.internal.source.annotations.xml.mocker.EntityMappingsMocker; import org.hibernate.metamodel.spi.source.MappingException; import org.hibernate.metamodel.spi.source.MappingNotFoundException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.service.ServiceRegistry; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; +import org.jboss.logging.Logger; +import org.w3c.dom.Document; /** * Entry point into working with sources of metadata information ({@code hbm.xml}, annotations). Tell Hibernate @@ -508,6 +507,11 @@ public class MetadataSources { // discovered while processing the annotations. To keep this behavior we index all classes in the // hierarchy (see also HHH-7484) indexClass( clazz.getSuperclass(), indexer, processedNames ); + + // Similarly, add any inner classes (see HHH-7678). + for ( Class declaredClass : clazz.getDeclaredClasses() ) { + indexClass( declaredClass, indexer, processedNames ); + } } private void indexResource(String resourceName, Indexer indexer, Set processedNames) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java index 33f1a847a0..044242d925 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/ConfiguredClass.java @@ -427,18 +427,20 @@ public class ConfiguredClass { final ResolvedMember[] resolvedMembers = Field.class.isInstance( member ) ? resolvedType.getMemberFields() : resolvedType .getMemberMethods(); ResolvedMember resolvedMember = findResolvedMember( member.getName(), resolvedMembers ); - Class referencedEntityType = resolveCollectionValuedReferenceType( resolvedMember ); + Class attributeType = resolvedMember.getType().getErasedType(); + Class referencedCollectionType = resolveCollectionValuedReferenceType( resolvedMember ); final Map> annotations = JandexHelper.getMemberAnnotations( classInfo, member.getName() ); - MappedAttribute.Nature attributeNature = determineAttributeNature( annotations, referencedEntityType ); + MappedAttribute.Nature attributeNature = determineAttributeNature( + annotations, attributeType, referencedCollectionType ); String accessTypeString = accessType.toString().toLowerCase(); switch ( attributeNature ) { case BASIC: { BasicAttribute attribute = BasicAttribute.createSimpleAttribute( attributeName, - resolvedMember.getType().getErasedType(), + attributeType, attributeNature, annotations, accessTypeString, @@ -463,7 +465,7 @@ public class ConfiguredClass { case EMBEDDED_ID: { final BasicAttribute attribute = BasicAttribute.createSimpleAttribute( attributeName, - resolvedMember.getType().getErasedType(), + attributeType, attributeNature, annotations, accessTypeString, @@ -471,13 +473,11 @@ public class ConfiguredClass { ); idAttributeMap.put( attributeName, attribute ); } - //$FALL-THROUGH$ case EMBEDDED: { final AnnotationInstance targetAnnotation = JandexHelper.getSingleAnnotation( getClassInfo(), HibernateDotNames.TARGET ); - Class attributeType = resolvedMember.getType().getErasedType(); if ( targetAnnotation != null ) { attributeType = localBindingContext.locateClassByName( JandexHelper.getValue( targetAnnotation, "value", String.class ) @@ -507,7 +507,7 @@ public class ConfiguredClass { classInfo, attributeName, resolvedMember.getType().getErasedType(), - referencedEntityType, + referencedCollectionType, attributeNature, accessTypeString, annotations, @@ -563,11 +563,15 @@ public class ConfiguredClass { * Given the annotations defined on a persistent attribute this methods determines the attribute type. * * @param annotations the annotations defined on the persistent attribute + * @param type the attribute's type * @param referencedCollectionType the type of the collection element in case the attribute is collection valued * * @return an instance of the {@code AttributeType} enum */ - private MappedAttribute.Nature determineAttributeNature(Map> annotations, Class referencedCollectionType) { + private MappedAttribute.Nature determineAttributeNature( Map> annotations, + Class attributeType, + Class referencedCollectionType ) { EnumMap discoveredAttributeTypes = new EnumMap( MappedAttribute.Nature.class ); @@ -591,16 +595,33 @@ public class ConfiguredClass { discoveredAttributeTypes.put( MappedAttribute.Nature.MANY_TO_MANY, manyToMany ); } - AnnotationInstance embedded = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED ); - if ( embedded != null ) { - discoveredAttributeTypes.put( MappedAttribute.Nature.EMBEDDED, embedded ); - } - AnnotationInstance embeddedId = JandexHelper.getSingleAnnotation( annotations, JPADotNames.EMBEDDED_ID ); if ( embeddedId != null ) { discoveredAttributeTypes.put( MappedAttribute.Nature.EMBEDDED_ID, embeddedId ); } + AnnotationInstance embedded = JandexHelper.getSingleAnnotation( + annotations, JPADotNames.EMBEDDED ); + if ( embedded != null ) { + discoveredAttributeTypes.put( MappedAttribute.Nature.EMBEDDED, + embedded ); + } else if ( embeddedId == null ) { + // For backward compatibility, we're allowing attributes of an + // @Embeddable type to leave off @Embedded. Check the type's + // annotations. (see HHH-7678) + // However, it's important to ignore this if the field is + // annotated with @EmbeddedId. + ClassInfo typeClassInfo = localBindingContext.getIndex() + .getClassByName( DotName.createSimple( attributeType.getName() ) ); + if ( typeClassInfo != null + && JandexHelper.getSingleAnnotation( + typeClassInfo.annotations(), + JPADotNames.EMBEDDABLE ) != null ) { + discoveredAttributeTypes.put( MappedAttribute.Nature.EMBEDDED, + null ); + } + } + AnnotationInstance elementCollection = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ELEMENT_COLLECTION diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessTest.java index fc52e6ce8e..b94a5f8b87 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/AccessTest.java @@ -23,29 +23,29 @@ */ package org.hibernate.test.annotations.access.jpa; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.test.annotations.access.Closet; -import org.hibernate.testing.FailureExpectedWithNewMetamodel; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.test.annotations.access.Closet; +import org.hibernate.testing.FailureExpectedWithNewMetamodel; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + /** * @author Emmanuel Bernard * @author Hardy Ferentschik */ -@FailureExpectedWithNewMetamodel public class AccessTest extends BaseCoreFunctionalTestCase { + + @FailureExpectedWithNewMetamodel @Test public void testDefaultConfigurationModeIsInherited() throws Exception { User john = new User(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java index 4cddbd4aaf..49f017f9aa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Gardenshed.java @@ -41,8 +41,12 @@ import javax.persistence.Transient; public class Gardenshed extends Woody { + private Integer id; + private String brand; + + @Access(javax.persistence.AccessType.FIELD) public long floors; @Transient @@ -66,7 +70,6 @@ public class Gardenshed // These 2 functions should not return in Hibernate, but the value should come from the field "floors" - @Access(javax.persistence.AccessType.FIELD) public long getFloors() { return this.floors + 2; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Square.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Square.java index c9dfef0a6c..d536d359fc 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Square.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/access/jpa/Square.java @@ -37,7 +37,6 @@ public class Square { private long id; - @Embedded private Position position; @Id @@ -50,6 +49,7 @@ public class Square { this.id = id; } + @Embedded public Position getPosition() { return position; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java index a55f24efe4..3c0b541372 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/DDLTest.java @@ -41,7 +41,6 @@ import org.junit.Test; * @author Emmanuel Bernard * @author Hardy Ferentschik */ -@FailureExpectedWithNewMetamodel public class DDLTest extends BaseCoreFunctionalTestCase { @Test public void testBasicDDL() { @@ -66,6 +65,7 @@ public class DDLTest extends BaseCoreFunctionalTestCase { assertEquals( column.getSize().getLength(), 5 ); } + @FailureExpectedWithNewMetamodel @Test public void testApplyOnManyToOne() throws Exception { Column column = SchemaUtil.getColumn( TvOwner.class, "tv", metadata() ); @@ -78,6 +78,7 @@ public class DDLTest extends BaseCoreFunctionalTestCase { assertTrue( "Notnull should not be applied on single tables", column.isNullable() ); } + @FailureExpectedWithNewMetamodel @Test public void testNotNullOnlyAppliedIfEmbeddedIsNotNullItself() throws Exception { Column column = SchemaUtil.getColumn( Tv.class, "tuner.frequency", metadata() ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Tv.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Tv.java index 3dca8f17f3..7ed9a3e12b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Tv.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/beanvalidation/Tv.java @@ -26,6 +26,7 @@ package org.hibernate.test.annotations.beanvalidation; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Date; + import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Id;