diff --git a/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java index 3b14a86287..d7f3845168 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java @@ -122,7 +122,7 @@ class MultiIdentifierLoadAccessImpl implements MultiIdentifierLoadAccess, @Override @SuppressWarnings( "unchecked" ) public List multiLoad(K... ids) { - return perform( () -> entityPersister.multiLoad( ids, session, this ) ); + return perform( () -> (List) entityPersister.multiLoad( ids, session, this ) ); } public List perform(Supplier> executor) { @@ -165,6 +165,6 @@ class MultiIdentifierLoadAccessImpl implements MultiIdentifierLoadAccess, @Override @SuppressWarnings( "unchecked" ) public List multiLoad(List ids) { - return perform( () -> entityPersister.multiLoad( ids.toArray( new Object[ 0 ] ), session, this ) ); + return perform( () -> (List) entityPersister.multiLoad( ids.toArray( new Object[ 0 ] ), session, this ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdLoaderStandard.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdLoaderStandard.java index eb63ea0376..20affff47e 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdLoaderStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdLoaderStandard.java @@ -31,6 +31,8 @@ import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; import org.hibernate.loader.entity.CacheEntityLoaderHelper; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryParameterBindings; @@ -59,31 +61,28 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { private final EntityPersister entityDescriptor; private final SessionFactoryImplementor sessionFactory; - private int idJdbcTypeCount = -1; + private final int idJdbcTypeCount; - public MultiIdLoaderStandard(EntityPersister entityDescriptor, SessionFactoryImplementor sessionFactory) { + public MultiIdLoaderStandard( + EntityPersister entityDescriptor, + PersistentClass bootDescriptor, + SessionFactoryImplementor sessionFactory) { this.entityDescriptor = entityDescriptor; + this.idJdbcTypeCount = bootDescriptor.getIdentifier().getColumnSpan(); this.sessionFactory = sessionFactory; + + assert idJdbcTypeCount > 0; } @Override - public EntityPersister getLoadable() { + public EntityMappingType getLoadable() { return entityDescriptor; } @Override public List load(Object[] ids, MultiIdLoadOptions loadOptions, SharedSessionContractImplementor session) { - // todo (6.0) : account for all of the `loadOptions` for now just do a simple load - // ^^ atm this is handled in `MultiIdentifierLoadAccess`. Need to decide on the design we want here... - // - see `SimpleNaturalIdMultiLoadAccessImpl` for example of alternative - assert ids != null; - if ( idJdbcTypeCount < 0 ) { - // can't do this in the ctor because of chicken-egg between this ctor and the persisters - idJdbcTypeCount = entityDescriptor.getIdentifierMapping().getJdbcTypeCount(); - } - if ( loadOptions.isOrderReturnEnabled() ) { return performOrderedMultiLoad( ids, session, loadOptions ); } @@ -105,7 +104,7 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { final JdbcEnvironment jdbcEnvironment = sessionFactory.getJdbcServices().getJdbcEnvironment(); final Dialect dialect = jdbcEnvironment.getDialect(); - final List result = CollectionHelper.arrayList( ids.length ); + final List result = CollectionHelper.arrayList( ids.length ); final LockOptions lockOptions = (loadOptions.getLockOptions() == null) ? new LockOptions( LockMode.NONE ) @@ -158,10 +157,10 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { ); managedEntity = persistenceContextEntry.getEntity(); - if ( managedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() && !persistenceContextEntry - .isManaged() ) { + if ( managedEntity != null + && !loadOptions.isReturnOfDeletedEntitiesEnabled() + && !persistenceContextEntry.isManaged() ) { // put a null in the result - //noinspection unchecked result.add( i, null ); continue; } @@ -177,7 +176,6 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { } if ( managedEntity != null ) { - //noinspection unchecked result.add( i, managedEntity ); continue; } @@ -221,12 +219,11 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { entity = null; } } - //noinspection unchecked result.set( position, entity ); } //noinspection unchecked - return (List) result; + return (List) result; } private List loadEntitiesById( @@ -236,8 +233,6 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { assert idsInBatch != null; assert ! idsInBatch.isEmpty(); - assert idJdbcTypeCount > 0; - final int numberOfIdsInBatch = idsInBatch.size(); if ( log.isTraceEnabled() ) { @@ -279,7 +274,7 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { ); } - // we should have used all of the JdbcParameter references (created bindings for all) + // we should have used all the JdbcParameter references (created bindings for all) assert offset == jdbcParameters.size(); final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst ) .translate( jdbcParameterBindings, QueryOptions.NONE ); @@ -297,7 +292,7 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { subSelectFetchableKeysHandler = null; } - List list = JdbcSelectExecutorStandardImpl.INSTANCE.list( + return JdbcSelectExecutorStandardImpl.INSTANCE.list( jdbcSelect, jdbcParameterBindings, new ExecutionContext() { @@ -336,8 +331,6 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { RowTransformerPassThruImpl.instance(), ListResultsConsumer.UniqueSemantic.FILTER ); - - return list; } private List performUnorderedMultiLoad( @@ -397,8 +390,9 @@ public class MultiIdLoaderStandard implements MultiIdEntityLoader { if ( loadOptions.isSessionCheckingEnabled() ) { managedEntity = persistenceContextEntry.getEntity(); - if ( managedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() && !persistenceContextEntry - .isManaged() ) { + if ( managedEntity != null + && !loadOptions.isReturnOfDeletedEntitiesEnabled() + && !persistenceContextEntry.isManaged() ) { foundAnyManagedEntities = true; result.add( null ); continue; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderStandard.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderStandard.java index 378d9a1e77..afb2d60418 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderStandard.java @@ -90,4 +90,9 @@ public class MultiNaturalIdLoaderStandard implements MultiNaturalIdLoader return results; } + + @Override + public EntityMappingType getLoadable() { + return entityDescriptor; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoadingBatcher.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoadingBatcher.java index d8160aec4c..b99ed70a4b 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoadingBatcher.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoadingBatcher.java @@ -162,7 +162,7 @@ public class MultiNaturalIdLoadingBatcher { } - final List result = JdbcSelectExecutorStandardImpl.INSTANCE.list( + return JdbcSelectExecutorStandardImpl.INSTANCE.list( jdbcSelect, jdbcParamBindings, new ExecutionContext() { @@ -201,7 +201,5 @@ public class MultiNaturalIdLoadingBatcher { RowTransformerPassThruImpl.instance(), ListResultsConsumer.UniqueSemantic.FILTER ); - - return result; } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiIdEntityLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiIdEntityLoader.java index 215a88f58e..bd3e8545af 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiIdEntityLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiIdEntityLoader.java @@ -9,16 +9,13 @@ package org.hibernate.loader.ast.spi; import java.util.List; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.persister.entity.EntityPersister; /** * Loader subtype for loading multiple entities by multiple identifier values. - * - * @author Steve Ebersole */ -public interface MultiIdEntityLoader extends Loader { - @Override - EntityPersister getLoadable(); - - List load(Object[] ids, MultiIdLoadOptions options, SharedSessionContractImplementor session); +public interface MultiIdEntityLoader extends MultiLoader { + /** + * Load multiple entities by id. The exact result depends on the passed options. + */ + List load(K[] ids, MultiIdLoadOptions options, SharedSessionContractImplementor session); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiLoader.java new file mode 100644 index 0000000000..85d95002c1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiLoader.java @@ -0,0 +1,19 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.loader.ast.spi; + +import org.hibernate.metamodel.mapping.EntityMappingType; + +/** + * Commonality for multi-loading + * + * @param The loaded model part + */ +public interface MultiLoader extends Loader { + @Override + EntityMappingType getLoadable(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiNaturalIdLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiNaturalIdLoader.java index 3129fc619c..b440a07251 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiNaturalIdLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/MultiNaturalIdLoader.java @@ -7,18 +7,15 @@ package org.hibernate.loader.ast.spi; import java.util.List; -import java.util.Map; -import java.util.function.Supplier; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.util.collections.CollectionHelper; /** * Loader for entities by multiple natural-ids * * @param The entity Java type */ -public interface MultiNaturalIdLoader { +public interface MultiNaturalIdLoader extends MultiLoader { /** * Load multiple entities by natural-id. The exact result depends on the passed options. * diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 73d0a6ae92..cb1c4c962d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -775,11 +775,7 @@ public abstract class AbstractEntityPersister singleIdEntityLoader = new SingleIdEntityLoaderStandardImpl<>( this, factory ); } - // todo (6.0) : allow a "max entities" to be passed (or determine based on Dialect?) indicating how many entities - // to load at once. i.e. it limits the number of the generated IN-list JDBC-parameters in a given - // PreparedStatement, opting to split the load into multiple JDBC operations to work around database - // limits on number of parameters, number of IN-list values, etc - multiIdEntityLoader = new MultiIdLoaderStandard<>( this, factory ); + multiIdEntityLoader = new MultiIdLoaderStandard<>( this, bootDescriptor, factory ); Iterator idColumns = bootDescriptor.getIdentifier().getColumnIterator(); int i = 0; @@ -4271,7 +4267,7 @@ public abstract class AbstractEntityPersister } @Override - public List multiLoad(Object[] ids, SharedSessionContractImplementor session, MultiIdLoadOptions loadOptions) { + public List multiLoad(Object[] ids, SharedSessionContractImplementor session, MultiIdLoadOptions loadOptions) { return multiIdEntityLoader.load( ids, loadOptions, session ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java index 0e5186ef50..8e0aa4a26b 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java @@ -218,6 +218,18 @@ public interface EntityPersister */ Serializable[] getQuerySpaces(); + /** + * The table names this entity needs to be synchronized against. + *

+ * Much like {@link #getPropertySpaces()}, except that here we include subclass + * entity spaces. + * + * @return The synchronization spaces. + */ + default String[] getSynchronizationSpaces() { + return (String[]) getQuerySpaces(); + } + /** * Returns an array of objects that identify spaces in which properties of * this entity are persisted, for instances of this class and its subclasses. @@ -500,7 +512,7 @@ public interface EntityPersister * * @return The loaded, matching entities */ - List multiLoad(Object[] ids, SharedSessionContractImplementor session, MultiIdLoadOptions loadOptions); + List multiLoad(Object[] ids, SharedSessionContractImplementor session, MultiIdLoadOptions loadOptions); /** * Do a version check (optional operation) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java index 326719ab9e..4b1c84b727 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java @@ -14,8 +14,10 @@ import org.hibernate.MappingException; import org.hibernate.cache.spi.access.CollectionDataAccess; import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.NaturalIdDataAccess; +import org.hibernate.internal.log.DeprecationLogger; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.spi.PersisterClassResolver; @@ -31,49 +33,45 @@ import org.hibernate.service.spi.ServiceRegistryImplementor; * @author Steve Ebersole */ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegistryAwareService { - - // todo : carry the notion of the creational parameters (parameter object) over to the persister constructors? - /** * The constructor signature for {@link EntityPersister} implementations */ - @SuppressWarnings({"WeakerAccess", "deprecation"}) - public static final Class[] ENTITY_PERSISTER_CONSTRUCTOR_ARGS = new Class[] { + @SuppressWarnings("WeakerAccess") + public static final Class[] ENTITY_PERSISTER_CONSTRUCTOR_ARGS = new Class[] { PersistentClass.class, EntityDataAccess.class, NaturalIdDataAccess.class, - PersisterCreationContext.class + RuntimeModelCreationContext.class }; /** * The constructor signature for {@link CollectionPersister} implementations */ - @SuppressWarnings({"WeakerAccess", "deprecation"}) - public static final Class[] COLLECTION_PERSISTER_CONSTRUCTOR_ARGS = new Class[] { + @SuppressWarnings("WeakerAccess") + public static final Class[] COLLECTION_PERSISTER_CONSTRUCTOR_ARGS = new Class[] { Collection.class, CollectionDataAccess.class, - PersisterCreationContext.class + RuntimeModelCreationContext.class }; - private ServiceRegistryImplementor serviceRegistry; + private PersisterClassResolver persisterClassResolver; @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { - this.serviceRegistry = serviceRegistry; + this.persisterClassResolver = serviceRegistry.getService( PersisterClassResolver.class ); } @Override - @SuppressWarnings( {"unchecked"}) public EntityPersister createEntityPersister( PersistentClass entityBinding, EntityDataAccess entityCacheAccessStrategy, NaturalIdDataAccess naturalIdCacheAccessStrategy, - @SuppressWarnings("deprecation") PersisterCreationContext creationContext) throws HibernateException { + RuntimeModelCreationContext creationContext) { // If the metadata for the entity specified an explicit persister class, use it... Class persisterClass = entityBinding.getEntityPersisterClass(); if ( persisterClass == null ) { // Otherwise, use the persister class indicated by the PersisterClassResolver service - persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( entityBinding ); + persisterClass = persisterClassResolver.getEntityPersisterClass( entityBinding ); } return createEntityPersister( @@ -90,39 +88,58 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi PersistentClass entityBinding, EntityDataAccess entityCacheAccessStrategy, NaturalIdDataAccess naturalIdCacheAccessStrategy, - @SuppressWarnings("deprecation") PersisterCreationContext creationContext) { + RuntimeModelCreationContext creationContext) { + final Constructor constructor = resolveEntityPersisterConstructor( persisterClass ); try { - final Constructor constructor = persisterClass.getConstructor( ENTITY_PERSISTER_CONSTRUCTOR_ARGS ); - try { - return constructor.newInstance( - entityBinding, - entityCacheAccessStrategy, - naturalIdCacheAccessStrategy, - creationContext - ); - } - catch (MappingException e) { - throw e; - } - catch (InvocationTargetException e) { - Throwable target = e.getTargetException(); - if ( target instanceof HibernateException ) { - throw (HibernateException) target; - } - else { - throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), target ); - } - } - catch (Exception e) { - throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), e ); - } + return constructor.newInstance( entityBinding, entityCacheAccessStrategy, naturalIdCacheAccessStrategy, creationContext ); } - catch (HibernateException e) { + catch (MappingException e) { throw e; } - catch (Exception e) { - throw new MappingException( "Could not get constructor for " + persisterClass.getName(), e ); + catch (InvocationTargetException e) { + final Throwable target = e.getTargetException(); + if ( target instanceof HibernateException ) { + throw (HibernateException) target; + } + else { + throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), target ); + } } + catch (Exception e) { + throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), e ); + } + } + + private Constructor resolveEntityPersisterConstructor(Class persisterClass) { + try { + return persisterClass.getConstructor( ENTITY_PERSISTER_CONSTRUCTOR_ARGS ); + } + catch (NoSuchMethodException noConstructorException) { + // we could not find the constructor... + // + // until we drop support for the legacy constructor signature, see if they define a + // constructor using that signature and use it if so + try { + final Constructor constructor = persisterClass.getConstructor( LEGACY_ENTITY_PERSISTER_CONSTRUCTOR_ARGS ); + // they do use the legacy signature... + + // warn them + DeprecationLogger.DEPRECATION_LOGGER.debugf( + "EntityPersister implementation defined constructor using legacy signature using `%s`; use `%s` instead", + PersisterCreationContext.class.getName(), + RuntimeModelCreationContext.class.getName() + ); + + // but use it + return constructor; + } + catch (NoSuchMethodException noLegacyConstructorException) { + // fall through to below + } + + throw new MappingException( "Could not find appropriate constructor for " + persisterClass.getName(), noConstructorException ); + } + } @Override @@ -130,14 +147,14 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi public CollectionPersister createCollectionPersister( Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, - @SuppressWarnings("deprecation") PersisterCreationContext creationContext) throws HibernateException { + RuntimeModelCreationContext creationContext) { // If the metadata for the collection specified an explicit persister class, use it Class persisterClass = collectionBinding.getCollectionPersisterClass(); if ( persisterClass == null ) { // Otherwise, use the persister class indicated by the PersisterClassResolver service - persisterClass = serviceRegistry.getService( PersisterClassResolver.class ) - .getCollectionPersisterClass( collectionBinding ); + persisterClass = persisterClassResolver.getCollectionPersisterClass( collectionBinding ); } + return createCollectionPersister( persisterClass, collectionBinding, cacheAccessStrategy, creationContext ); } @@ -146,43 +163,123 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, @SuppressWarnings("deprecation") PersisterCreationContext creationContext) { + final Constructor constructor = resolveCollectionPersisterConstructor( persisterClass ); try { - Constructor constructor = persisterClass.getConstructor( COLLECTION_PERSISTER_CONSTRUCTOR_ARGS ); - try { - return constructor.newInstance( - collectionBinding, - cacheAccessStrategy, - creationContext - ); - } - catch (MappingException e) { - throw e; - } - catch (InvocationTargetException e) { - Throwable target = e.getTargetException(); - if ( target instanceof HibernateException ) { - throw (HibernateException) target; - } - else { - throw new MappingException( - String.format( - "Could not instantiate collection persister implementor `%s` for collection-role `%s`", - persisterClass.getName(), - collectionBinding.getRole() - ), - target - ); - } - } - catch (Exception e) { - throw new MappingException( "Could not instantiate collection persister " + persisterClass.getName(), e ); - } + return constructor.newInstance( collectionBinding, cacheAccessStrategy, creationContext ); } catch (MappingException e) { throw e; } + catch (InvocationTargetException e) { + Throwable target = e.getTargetException(); + if ( target instanceof HibernateException ) { + throw (HibernateException) target; + } + else { + throw new MappingException( + String.format( + "Could not instantiate collection persister implementor `%s` for collection-role `%s`", + persisterClass.getName(), + collectionBinding.getRole() + ), + target + ); + } + } catch (Exception e) { - throw new MappingException( "Could not get constructor for " + persisterClass.getName(), e ); + throw new MappingException( "Could not instantiate collection persister " + persisterClass.getName(), e ); } } + + private Constructor resolveCollectionPersisterConstructor(Class persisterClass) { + try { + return persisterClass.getConstructor( COLLECTION_PERSISTER_CONSTRUCTOR_ARGS ); + } + catch (NoSuchMethodException noConstructorException) { + // we could not find the constructor... + // + // until we drop support for the legacy constructor signature, see if they define a + // constructor using that signature and use it if so + try { + final Constructor constructor = persisterClass.getConstructor( LEGACY_COLLECTION_PERSISTER_CONSTRUCTOR_ARGS ); + // they do use the legacy signature... + + // warn them + DeprecationLogger.DEPRECATION_LOGGER.debugf( + "CollectionPersister implementation defined constructor using legacy signature using `%s`; use `%s` instead", + PersisterCreationContext.class.getName(), + RuntimeModelCreationContext.class.getName() + ); + + // but use it + return constructor; + } + catch (NoSuchMethodException noLegacyConstructorException) { + // fall through to below + } + + throw new MappingException( "Could not find appropriate constructor for " + persisterClass.getName(), noConstructorException ); + } + } + + + /** + * The legacy constructor signature for {@link EntityPersister} implementations + * + * @deprecated (as of 6.0) - use {@link #ENTITY_PERSISTER_CONSTRUCTOR_ARGS} instead + */ + @Deprecated + private static final Class[] LEGACY_ENTITY_PERSISTER_CONSTRUCTOR_ARGS = new Class[] { + PersistentClass.class, + EntityDataAccess.class, + NaturalIdDataAccess.class, + PersisterCreationContext.class + }; + + @Override + public EntityPersister createEntityPersister( + PersistentClass entityBinding, + EntityDataAccess entityCacheAccessStrategy, + NaturalIdDataAccess naturalIdCacheAccessStrategy, + @SuppressWarnings("deprecation") PersisterCreationContext creationContext) { + DeprecationLogger.DEPRECATION_LOGGER.debugf( + "Encountered use of deprecated `PersisterFactory#createEntityPersister` form accepting `%s`; use form accepting `%s` instead", + PersisterCreationContext.class.getName(), + RuntimeModelCreationContext.class.getName() + ); + + return createEntityPersister( + entityBinding, + entityCacheAccessStrategy, + naturalIdCacheAccessStrategy, + (RuntimeModelCreationContext) creationContext + ); + } + + /** + * The constructor signature for {@link CollectionPersister} implementations + * + * @deprecated (as of 6.0) - use {@link #COLLECTION_PERSISTER_CONSTRUCTOR_ARGS} instead + */ + @Deprecated + private static final Class[] LEGACY_COLLECTION_PERSISTER_CONSTRUCTOR_ARGS = new Class[] { + Collection.class, + CollectionDataAccess.class, + PersisterCreationContext.class + }; + + + @Override + public CollectionPersister createCollectionPersister( + Collection collectionBinding, + CollectionDataAccess cacheAccessStrategy, + @SuppressWarnings("deprecation") PersisterCreationContext creationContext) throws HibernateException { + DeprecationLogger.DEPRECATION_LOGGER.debugf( + "Encountered use of deprecated `PersisterFactory#createCollectionPersister` form accepting `%s`; use form accepting `%s` instead", + PersisterCreationContext.class.getName(), + RuntimeModelCreationContext.class.getName() + ); + + return createCollectionPersister( collectionBinding, cacheAccessStrategy, (RuntimeModelCreationContext) creationContext ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java index d4d044c7b9..f379e58e56 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/spi/PersisterFactory.java @@ -12,6 +12,7 @@ import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.NaturalIdDataAccess; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.Service; @@ -22,6 +23,43 @@ import org.hibernate.service.Service; * @author Steve Ebersole */ public interface PersisterFactory extends Service { + /** + * Create an entity persister instance. + * + * @param entityBinding The mapping information describing the entity + * @param entityCacheAccessStrategy The cache access strategy for the entity region + * @param naturalIdCacheAccessStrategy The cache access strategy for the entity's natural-id cross-ref region + * @param creationContext Access to additional information needed to create the EntityPersister + */ + default EntityPersister createEntityPersister( + PersistentClass entityBinding, + EntityDataAccess entityCacheAccessStrategy, + NaturalIdDataAccess naturalIdCacheAccessStrategy, + RuntimeModelCreationContext creationContext) { + // for now, to minimize impact on existing custom impls, default this form to delegate to the original + return createEntityPersister( + entityBinding, + entityCacheAccessStrategy, + naturalIdCacheAccessStrategy, + (PersisterCreationContext) creationContext + ); + } + + /** + * Create a collection persister instance. + * + * @param collectionBinding The mapping information describing the collection + * @param cacheAccessStrategy The cache access strategy for the collection region + * @param creationContext Access to additional information needed to create an EntityPersister + */ + default CollectionPersister createCollectionPersister( + Collection collectionBinding, + CollectionDataAccess cacheAccessStrategy, + RuntimeModelCreationContext creationContext) { + // for now, to minimize impact on existing custom impls, default this form to delegate to the original + return createCollectionPersister( collectionBinding, cacheAccessStrategy, (PersisterCreationContext) creationContext ); + } + /** * Create an entity persister instance. * @@ -32,8 +70,10 @@ public interface PersisterFactory extends Service { * * @return An appropriate entity persister instance. * - * @throws HibernateException Indicates a problem building the persister. + * @deprecated (since 6.0) use {@link #createEntityPersister(PersistentClass, EntityDataAccess, NaturalIdDataAccess, RuntimeModelCreationContext)} + * instead */ + @Deprecated EntityPersister createEntityPersister( PersistentClass entityBinding, EntityDataAccess entityCacheAccessStrategy, @@ -47,13 +87,12 @@ public interface PersisterFactory extends Service { * @param cacheAccessStrategy The cache access strategy for the collection region * @param creationContext Access to additional information needed to create an EntityPersister * - * @return An appropriate collection persister instance. - * - * @throws HibernateException Indicates a problem building the persister. + * @deprecated (since 6.0) use {@link #createCollectionPersister(Collection, CollectionDataAccess, RuntimeModelCreationContext)} + * instead */ + @Deprecated CollectionPersister createCollectionPersister( Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, - PersisterCreationContext creationContext) throws HibernateException; - + PersisterCreationContext creationContext); }