diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index b7282edfd7..8ea14e926b 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -713,4 +713,13 @@ public interface AvailableSettings { * do not attempt to create unique constraints on a schema update */ public static final String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy"; + + /** + * If enabled, an entity's member field types and method return types will automatically be indexed. This allows, + * for example, auto-discovery of @Embeddables without explicitly listing them in the annotated classes. This + * setting will also check classes identified by certain annotations (such as @Target). JPA requires these classes + * to be identified in the annotated classes, however legacy Hibernate behavior was to allow it. Due to the + * performance hit, disabled by default. + */ + public static final String ENABLE_AUTO_INDEX_MEMBER_TYPES = "hibernate.enable_auto_index_member_types"; } 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 ce9e3390d0..c0fc768290 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java @@ -562,15 +562,19 @@ public class MetadataSources { return new EntityMappingsMocker( collectedOrmXmlMappings, jandexView, serviceRegistry ).mockNewIndex(); } - + public IndexView buildJandexView() { + return buildJandexView( false ); + } + + public IndexView buildJandexView(boolean autoIndexMemberTypes) { // create a jandex index from the annotated classes Indexer indexer = new Indexer(); Set> processedClasses = new HashSet>(); for ( Class clazz : getAnnotatedClasses() ) { - indexClass( clazz, indexer, processedClasses ); + indexClass( clazz, indexer, processedClasses, autoIndexMemberTypes ); } for ( String className : getAnnotatedClassNames() ) { @@ -585,7 +589,7 @@ public class MetadataSources { return wrapJandexView( indexer.complete() ); } - private void indexClass(Class clazz, Indexer indexer, Set> processedClasses) { + private void indexClass(Class clazz, Indexer indexer, Set> processedClasses, boolean autoIndexMemberTypes) { if ( clazz == null || clazz == Object.class || processedClasses.contains( clazz ) ) { return; @@ -600,35 +604,42 @@ public class MetadataSources { // necessary to add all annotated classes. Entities would be enough. Mapped superclasses would be // discovered while processing the annotations. To keep this behavior we index all classes in the // hierarchy (see also HHH-7484) - indexClass( clazz.getSuperclass(), indexer, processedClasses ); + indexClass( clazz.getSuperclass(), indexer, processedClasses, autoIndexMemberTypes ); - // For backward compatibility, don't require @Embeddable - // classes to be explicitly identified. - // Automatically find them by checking the fields' types. - for ( Class fieldType : ReflectHelper.getMemberTypes( clazz ) ) { - if ( !fieldType.isPrimitive() && fieldType != Object.class ) { - try { - IndexView fieldIndex = JandexHelper.indexForClass( - serviceRegistry.getService( ClassLoaderService.class ), - fieldType ); - if ( !fieldIndex.getAnnotations( - JPADotNames.EMBEDDABLE ).isEmpty() ) { - indexClass( fieldType, indexer, processedClasses ); - } - } catch ( Exception e ) { - // do nothing - } - } + // Similarly, index any inner class. + for ( Class innerClass : clazz.getDeclaredClasses() ) { + indexClass( innerClass, indexer, processedClasses, autoIndexMemberTypes ); } - // Also check for classes within a @Target annotation. - for ( AnnotationInstance targetAnnotation : JandexHelper.getAnnotations( - classInfo, HibernateDotNames.TARGET ) ) { - String targetClassName = targetAnnotation.value().asClass().name() - .toString(); - Class targetClass = serviceRegistry.getService( - ClassLoaderService.class ).classForName( targetClassName ); - indexClass(targetClass, indexer, processedClasses ); + if ( autoIndexMemberTypes ) { + // If autoIndexMemberTypes, don't require @Embeddable + // classes to be explicitly identified. + // Automatically find them by checking the fields' types. + for ( Class fieldType : ReflectHelper.getMemberTypes( clazz ) ) { + if ( !fieldType.isPrimitive() && fieldType != Object.class ) { + try { + IndexView fieldIndex = JandexHelper.indexForClass( + serviceRegistry.getService( ClassLoaderService.class ), + fieldType ); + if ( !fieldIndex.getAnnotations( + JPADotNames.EMBEDDABLE ).isEmpty() ) { + indexClass( fieldType, indexer, processedClasses, autoIndexMemberTypes ); + } + } catch ( Exception e ) { + // do nothing + } + } + } + + // Also check for classes within a @Target annotation. + for ( AnnotationInstance targetAnnotation : JandexHelper.getAnnotations( + classInfo, HibernateDotNames.TARGET ) ) { + String targetClassName = targetAnnotation.value().asClass().name() + .toString(); + Class targetClass = serviceRegistry.getService( + ClassLoaderService.class ).classForName( targetClassName ); + indexClass(targetClass, indexer, processedClasses, autoIndexMemberTypes ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java index ef9399b3c5..cb60903430 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java @@ -45,11 +45,14 @@ import org.hibernate.annotations.common.util.StringHelper; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.CacheRegionDefinition; import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.dialect.Dialect; import org.hibernate.engine.ResultSetMappingDefinition; +import org.hibernate.engine.config.spi.ConfigurationService; +import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.NamedQueryDefinition; @@ -175,9 +178,11 @@ public class MetadataImpl implements MetadataImplementor, Serializable { }; // todo : cache the built index if no inputs have changed (look at gradle-style hashing for up-to-date checking) + boolean autoIndexMemberTypes = serviceRegistry.getService( ConfigurationService.class ).getSetting( + AvailableSettings.ENABLE_AUTO_INDEX_MEMBER_TYPES, StandardConverters.BOOLEAN, false ); final IndexView jandexView = options.getJandexView() != null ? metadataSources.wrapJandexView( options.getJandexView() ) - : metadataSources.buildJandexView(); + : metadataSources.buildJandexView( autoIndexMemberTypes ); Collection tables = jandexView.getAnnotations( JPADotNames.TABLE ); final MetadataSourceProcessor[] metadataSourceProcessors; if ( options.getMetadataSourceProcessingOrder() == MetadataSourceProcessingOrder.HBM_FIRST ) { diff --git a/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java index a0875de455..05b4bca1a9 100644 --- a/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeAttributeResultSetProcessorTest.java @@ -23,6 +23,10 @@ */ package org.hibernate.loader; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + import java.io.Serializable; import java.math.BigDecimal; import java.sql.Connection; @@ -33,6 +37,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; + import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; @@ -44,8 +49,6 @@ import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.ManyToOne; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.QueryParameters; @@ -61,15 +64,10 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext; import org.hibernate.loader.spi.NamedParameterContext; import org.hibernate.loader.spi.NoOpLoadPlanAdvisor; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.test.component.cascading.toone.PersonalInfo; -import org.hibernate.testing.FailureExpected; import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; +import org.junit.Test; /** * @author Gail Badner @@ -78,7 +76,8 @@ public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCo @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Customer.class }; + return new Class[] { Person.class, Customer.class, Address.class, AddressType.class, Customer.class, + Investment.class, MonetaryAmount.class }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeIdResultSetProcessorTest.java b/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeIdResultSetProcessorTest.java index 8b0968f70c..942eeea1b0 100644 --- a/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeIdResultSetProcessorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/loader/EncapsulatedCompositeIdResultSetProcessorTest.java @@ -73,7 +73,7 @@ public class EncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunct @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Parent.class, CardField.class, Card.class }; + return new Class[] { Parent.class, CardField.class, Card.class, ParentPK.class, CardFieldPK.class }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java index eed70d2ea9..5d5f3acf22 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/JoinedSubclassTest.java @@ -127,6 +127,7 @@ public class JoinedSubclassTest extends BaseCoreFunctionalTestCase { AmericaCupClass.class, Country.class, Vegetable.class, + VegetablePk.class, Carrot.class, Tomato.class }; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java index 07e68e0071..0c6c6c31c2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/CollectionElementTest.java @@ -28,7 +28,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -276,7 +275,11 @@ public class CollectionElementTest extends BaseCoreFunctionalTestCase { Boy.class, Country.class, TestCourse.class, - Matrix.class + Matrix.class, + LocalizedString.class, + Toy.class, + CountryAttitude.class, + Brand.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java index 25feb8ef00..4c643de6dd 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/OrderByTest.java @@ -127,7 +127,9 @@ public class OrderByTest extends BaseCoreFunctionalTestCase { return new Class[] { Products.class, Widgets.class, - BugSystem.class + BugSystem.class, + Bug.class, + Person.class }; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java index 611f53e699..7727623b89 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/embeddables/withcustomenumdef/TestBasicOps.java @@ -36,7 +36,7 @@ import static junit.framework.Assert.assertEquals; public class TestBasicOps extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Query.class }; + return new Class[] { Query.class, Location.class }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java index bcca215f5c..1394cc9923 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/collectionelement/ordered/ElementCollectionSortingTest.java @@ -41,7 +41,7 @@ import org.junit.Test; public class ElementCollectionSortingTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class }; + return new Class[] { Person.class, Address.class }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java index b2de1a508d..9e6e3452aa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/EmbeddedTest.java @@ -540,7 +540,11 @@ public class EmbeddedTest extends BaseCoreFunctionalTestCase { InternetFavorites.class, FixedLeg.class, FloatLeg.class, - Swap.class + Swap.class, + RegionalArticlePk.class, + LegalStructure.class, + Summary.class, + URLFavorite.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java index f2833230c5..12589f9608 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java @@ -38,7 +38,7 @@ import static org.junit.Assert.assertEquals; public class EmbeddableWithMany2OneTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Country.class }; + return new Class[] { Person.class, Country.class, Address.class }; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java index c1bde2e1e9..0aac836079 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/join/JoinTest.java @@ -266,6 +266,7 @@ public class JoinTest extends BaseCoreFunctionalTestCase { Death.class, Cat.class, Dog.class, + DogPk.class, A.class, B.class, C.class, diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/complex/ManyToManyComplexTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/complex/ManyToManyComplexTest.java index 9da7a96e56..d11e1193d9 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/complex/ManyToManyComplexTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/manytomany/complex/ManyToManyComplexTest.java @@ -331,7 +331,9 @@ public class ManyToManyComplexTest Employee.class, Contractor.class, PhoneNumber.class, - ProgramManager.class + ProgramManager.class, + ContactInfo.class, + JobInfo.class }; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java index 9091e010de..388e409367 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/query/QueryAndSQLTest.java @@ -470,7 +470,8 @@ public class QueryAndSQLTest extends BaseCoreFunctionalTestCase { Captain.class, Chaos.class, CasimirParticle.class, - AllTables.class + AllTables.class, + Dimensions.class }; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java b/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java index 0adb98c960..34903b6515 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/component/basic2/ComponentJoinsTest.java @@ -40,7 +40,7 @@ public class ComponentJoinsTest extends BaseCoreFunctionalTestCase { return new Class[] { Person.class, Component.class, - Component.Emb.Stuff.class }; + Name.class}; } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java index 9c8b8e978f..38ea803ce0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/propertyref/DoesNotWorkTest.java @@ -40,7 +40,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; public class DoesNotWorkTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] {DoesNotWork.class}; + return new Class[] { DoesNotWork.class, DoesNotWorkPk.class }; } @Override