diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java index 8c46af8736..7d6e7a4a29 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java @@ -243,7 +243,8 @@ public class PersistentBag extends AbstractPersistentCollection implements @Override public void initializeEmptyCollection(CollectionPersister persister) { assert bag == null; - bag = (List) persister.getCollectionType().instantiate( 0 ); + //noinspection unchecked + bag = (List) persister.getCollectionSemantics().instantiateRaw( 0, persister ); endRead(); } diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java index 9a19104aef..d9fa3ade10 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java @@ -87,7 +87,8 @@ public class PersistentList extends AbstractPersistentCollection implement @SuppressWarnings("unchecked") public void initializeEmptyCollection(CollectionPersister persister) { assert list == null; - list = (List) persister.getCollectionType().instantiate( 0 ); + //noinspection unchecked + list = (List) persister.getCollectionSemantics().instantiateRaw( 0, persister ); endRead(); } @@ -121,7 +122,7 @@ public class PersistentList extends AbstractPersistentCollection implement final int size = array.length; assert list == null; - this.list = (List) persister.getCollectionType().instantiate( size ); + list = (List) persister.getCollectionSemantics().instantiateRaw( size, persister ); for ( Serializable arrayElement : array ) { list.add( (E) persister.getElementType().assemble( arrayElement, getSession(), owner ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java index 5805d79140..c5f77fb03a 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentMap.java @@ -94,7 +94,8 @@ public class PersistentMap extends AbstractPersistentCollection implemen @Override public void initializeEmptyCollection(CollectionPersister persister) { assert map == null; - map = (Map) persister.getCollectionType().instantiate( 0 ); + //noinspection unchecked + map = (Map) persister.getCollectionSemantics().instantiateRaw( 0, persister ); endRead(); } diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentSet.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentSet.java index 6f771b8911..00bb9e874d 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentSet.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentSet.java @@ -12,6 +12,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; @@ -96,7 +97,8 @@ public class PersistentSet extends AbstractPersistentCollection implements @Override public void initializeEmptyCollection(CollectionPersister persister) { assert set == null; - set = (Set) persister.getCollectionType().instantiate( 0 ); + //noinspection unchecked + set = (Set) persister.getCollectionSemantics().instantiateRaw( 0, persister ); endRead(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 9620998e41..3c577a5aa0 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -210,7 +210,6 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im sessionFactoryOptions = options; serviceRegistry = getServiceRegistry( options, this ); - eventEngine = new EventEngine( bootMetamodel, this ); bootMetamodel.initSessionFactory( this ); @@ -262,87 +261,13 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im // registry here, and doing the engine later queryEngine = QueryEngine.from( this, bootMetamodel ); - // this is where creation of the runtime metamodel happens + // create runtime metamodels (mapping and JPA) final RuntimeMetamodelsImpl runtimeMetamodelsImpl = new RuntimeMetamodelsImpl(); runtimeMetamodels = runtimeMetamodelsImpl; - new RuntimeModelCreationContext() { - final MappingMetamodelImpl mappingMetamodelImpl = - new MappingMetamodelImpl( typeConfiguration, serviceRegistry ); - { - // need to set this before calling finishInitialization() - runtimeMetamodelsImpl.setMappingMetamodel( mappingMetamodelImpl ); - // because this calls back to the RuntimeMetamodelsImplementor - mappingMetamodelImpl.finishInitialization( this ); - // need to set this after calling finishInitialization() - runtimeMetamodelsImpl.setJpaMetamodel( mappingMetamodelImpl.getJpaMetamodel() ); - } - - @Override - public BootstrapContext getBootstrapContext() { - return bootstrapContext; - } - - @Override - public SessionFactoryImplementor getSessionFactory() { - // this is bad, we're not yet fully-initialized - return SessionFactoryImpl.this; - } - - @Override - public MetadataImplementor getBootModel() { - return bootMetamodel; - } - - @Override - public MappingMetamodelImplementor getDomainModel() { - return mappingMetamodelImpl; - } - - @Override - public CacheImplementor getCache() { - return cacheAccess; - } - - @Override - public Map getSettings() { - return settings; - } - - @Override - public Dialect getDialect() { - return jdbcServices.getDialect(); - } - - @Override - public SqmFunctionRegistry getFunctionRegistry() { - return queryEngine.getSqmFunctionRegistry(); - } - - @Override - public TypeConfiguration getTypeConfiguration() { - return typeConfiguration; - } - - @Override - public SessionFactoryOptions getSessionFactoryOptions() { - return options; - } - - @Override - public JdbcServices getJdbcServices() { - return jdbcServices; - } - - @Override - public SqlStringGenerationContext getSqlStringGenerationContext() { - return sqlStringGenerationContext; - } - - @Override - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - }; + final MappingMetamodelImpl mappingMetamodelImpl = new MappingMetamodelImpl( typeConfiguration, serviceRegistry ); + runtimeMetamodelsImpl.setMappingMetamodel( mappingMetamodelImpl ); + initializeMappingModel( mappingMetamodelImpl, bootstrapContext, bootMetamodel, options ); + runtimeMetamodelsImpl.setJpaMetamodel( mappingMetamodelImpl.getJpaMetamodel() ); // this needs to happen after the mapping metamodel is // completely built, since we need to use the persisters @@ -385,6 +310,96 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im LOG.debug( "Instantiated SessionFactory" ); } + private void initializeMappingModel( + MappingMetamodelImpl mappingMetamodelImpl, + BootstrapContext bootstrapContext, + MetadataImplementor bootMetamodel, + SessionFactoryOptions options) { + final TypeConfiguration typeConfiguration = mappingMetamodelImpl.getTypeConfiguration(); + mappingMetamodelImpl.finishInitialization( runtimeModelCreationContext( + bootstrapContext, + bootMetamodel, + mappingMetamodelImpl, + typeConfiguration, + options + ) ); + } + + private RuntimeModelCreationContext runtimeModelCreationContext( + BootstrapContext bootstrapContext, + MetadataImplementor bootMetamodel, + MappingMetamodelImplementor mappingMetamodel, + TypeConfiguration typeConfiguration, + SessionFactoryOptions options) { + return new RuntimeModelCreationContext() { + @Override + public BootstrapContext getBootstrapContext() { + return bootstrapContext; + } + + @Override + public SessionFactoryImplementor getSessionFactory() { + // this is bad, we're not yet fully-initialized + return SessionFactoryImpl.this; + } + + @Override + public MetadataImplementor getBootModel() { + return bootMetamodel; + } + + @Override + public MappingMetamodelImplementor getDomainModel() { + return mappingMetamodel; + } + + @Override + public CacheImplementor getCache() { + return cacheAccess; + } + + @Override + public Map getSettings() { + return settings; + } + + @Override + public Dialect getDialect() { + return jdbcServices.getDialect(); + } + + @Override + public SqmFunctionRegistry getFunctionRegistry() { + return queryEngine.getSqmFunctionRegistry(); + } + + @Override + public TypeConfiguration getTypeConfiguration() { + return typeConfiguration; + } + + @Override + public SessionFactoryOptions getSessionFactoryOptions() { + return options; + } + + @Override + public JdbcServices getJdbcServices() { + return jdbcServices; + } + + @Override + public SqlStringGenerationContext getSqlStringGenerationContext() { + return sqlStringGenerationContext; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + }; + } + private static Map createGenerators( JdbcServices jdbcServices, SqlStringGenerationContext sqlStringGenerationContext, diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java index 04a3eedd13..d42419701d 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java @@ -44,6 +44,20 @@ public class CollectionElementLoaderByIndex implements Loader { private final int keyJdbcCount; + /** + * Shortened form of {@link #CollectionElementLoaderByIndex(PluralAttributeMapping, int, LoadQueryInfluencers, SessionFactoryImplementor)} + * which applied the collection mapping's {@linkplain PluralAttributeMapping.IndexMetadata#getListIndexBase()} + */ + public CollectionElementLoaderByIndex( + PluralAttributeMapping attributeMapping, + LoadQueryInfluencers influencers, + SessionFactoryImplementor sessionFactory) { + this( attributeMapping, attributeMapping.getIndexMetadata().getListIndexBase(), influencers, sessionFactory ); + } + + /** + * @param baseIndex A base value to apply to the relational index values processed on {@link #incrementIndexByBase} + */ public CollectionElementLoaderByIndex( PluralAttributeMapping attributeMapping, int baseIndex, @@ -144,11 +158,20 @@ public class CollectionElementLoaderByIndex implements Loader { return list.get( 0 ); } + /** + * If the index being loaded by for a List and the mapping specified a + * {@linkplain org.hibernate.annotations.ListIndexBase base-index}, this will return + * the passed {@code index} value incremented by the base. Otherwise, the passed {@code index} + * is returned. + * + * @param index The relational index value; specifically without any mapped base applied + * + * @return The appropriately incremented base + */ protected Object incrementIndexByBase(Object index) { - if ( baseIndex != 0 ) { - index = (Integer) index + baseIndex; + if ( baseIndex > 0 ) { + return (Integer) index + baseIndex; } return index; } - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/CollectionClassification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/CollectionClassification.java index 236b116727..181f46d407 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/CollectionClassification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/CollectionClassification.java @@ -27,30 +27,30 @@ public enum CollectionClassification { * An Object or primitive array. Roughly follows the semantics * of {@link #LIST} */ - ARRAY( PluralAttribute.CollectionType.COLLECTION ), + ARRAY( PluralAttribute.CollectionType.COLLECTION, true ), /** * A non-unique, unordered collection. Represented * as {@link java.util.Collection} or {@link java.util.List} */ - BAG( PluralAttribute.CollectionType.COLLECTION ), + BAG( PluralAttribute.CollectionType.COLLECTION, false ), /** * A {@link #BAG} with a generated id for each element */ - ID_BAG( PluralAttribute.CollectionType.COLLECTION ), + ID_BAG( PluralAttribute.CollectionType.COLLECTION, false ), /** * A non-unique, ordered collection following the requirements of {@link java.util.List} * * @see org.hibernate.cfg.AvailableSettings#DEFAULT_LIST_SEMANTICS */ - LIST( PluralAttribute.CollectionType.LIST ), + LIST( PluralAttribute.CollectionType.LIST, true ), /** * A unique, unordered collection following the requirements of {@link java.util.Set} */ - SET( PluralAttribute.CollectionType.SET ), + SET( PluralAttribute.CollectionType.SET, false ), /** * A sorted {@link #SET} using either natural sorting of the elements or a @@ -60,7 +60,7 @@ public enum CollectionClassification { * @see org.hibernate.annotations.SortNatural * @see org.hibernate.annotations.SortComparator */ - SORTED_SET( PluralAttribute.CollectionType.SET ), + SORTED_SET( PluralAttribute.CollectionType.SET, false ), /** * A {@link #SET} that is ordered using an order-by fragment @@ -71,12 +71,12 @@ public enum CollectionClassification { * @see jakarta.persistence.OrderBy * @see org.hibernate.annotations.OrderBy */ - ORDERED_SET( PluralAttribute.CollectionType.SET ), + ORDERED_SET( PluralAttribute.CollectionType.SET, false ), /** * A collection following the semantics of {@link java.util.Map} */ - MAP( PluralAttribute.CollectionType.MAP ), + MAP( PluralAttribute.CollectionType.MAP, true ), /** * A sorted {@link #MAP} using either natural sorting of the keys or a @@ -86,7 +86,7 @@ public enum CollectionClassification { * @see org.hibernate.annotations.SortNatural * @see org.hibernate.annotations.SortComparator */ - SORTED_MAP( PluralAttribute.CollectionType.MAP ), + SORTED_MAP( PluralAttribute.CollectionType.MAP, true ), /** * A {@link #MAP} that is ordered using an order-by fragment @@ -97,18 +97,29 @@ public enum CollectionClassification { * @see jakarta.persistence.OrderBy * @see org.hibernate.annotations.OrderBy */ - ORDERED_MAP( PluralAttribute.CollectionType.MAP ); + ORDERED_MAP( PluralAttribute.CollectionType.MAP, true ); private final PluralAttribute.CollectionType jpaClassification; + private final boolean isIndexed; - CollectionClassification(PluralAttribute.CollectionType jpaClassification) { + CollectionClassification(PluralAttribute.CollectionType jpaClassification, boolean isIndexed) { this.jpaClassification = jpaClassification; + this.isIndexed = isIndexed; } public PluralAttribute.CollectionType toJpaClassification() { return jpaClassification; } + public boolean isIndexed() { + return isIndexed; + } + + public boolean isRowUpdatePossible() { + // anything other than BAG and SET + return this != BAG && this != SET; + } + /** * One of:
    *
  • {@link org.hibernate.metamodel.CollectionClassification} instance
  • @@ -174,9 +185,4 @@ public enum CollectionClassification { return null; } - - public boolean isRowUpdatePossible() { - // anything other than BAG and SET - return this != BAG && this != SET; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java index f7982192ba..7fc6edd437 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java @@ -19,6 +19,7 @@ import org.hibernate.Internal; import org.hibernate.boot.jaxb.mapping.JaxbEntity; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.LoadQueryInfluencers; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.MultiNaturalIdLoader; import org.hibernate.loader.ast.spi.NaturalIdLoader; @@ -458,6 +459,12 @@ public interface EntityMappingType */ MultiNaturalIdLoader getMultiNaturalIdLoader(); + /** + * Load an instance of the persistent class, by a unique key other + * than the primary key. + */ + Object loadByUniqueKey(String propertyName, Object uniqueKey, SharedSessionContractImplementor session); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Loadable diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java index b3bb939ab4..2e9a3b64ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java @@ -174,6 +174,7 @@ public class PluralAttributeMappingImpl else { baseIndex = -1; } + indexMetadata = new IndexMetadata() { @Override public CollectionPart getIndexDescriptor() { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/NavigableRole.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/NavigableRole.java index 3deb000a6d..f6e5125912 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/NavigableRole.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/NavigableRole.java @@ -7,18 +7,23 @@ package org.hibernate.metamodel.model.domain; import java.io.Serializable; -import java.util.Objects; -import org.hibernate.spi.DotIdentifierSequence; import org.hibernate.internal.util.StringHelper; +import org.hibernate.spi.DotIdentifierSequence; import org.hibernate.spi.NavigablePath; /** - * Poorly named. + * A compound path which represents a {@link org.hibernate.metamodel.mapping.ModelPart} + * and uniquely identifies it with the runtime metamodel. + *

    + * The {@linkplain #isRoot() root} will name either an + * {@linkplain org.hibernate.metamodel.MappingMetamodel#getEntityDescriptor entity} or + * {@linkplain org.hibernate.metamodel.MappingMetamodel#getCollectionDescriptor collection} * - * Should have been named `org.hibernate.metamodel.model.mapping.MappingRole` * - * Represents a compound path of `ModelPart` nodes rooted at an entity-name. + * @apiNote Poorly named. Should probably have been `org.hibernate.metamodel.model.mapping.MappingRole`; + * the term "navigable" here is meant to indicate that we could navigate to the specific + * {@link org.hibernate.metamodel.mapping.ModelPart} given the role. * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 610dd343d9..a8a459709f 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -6,7 +6,6 @@ */ package org.hibernate.persister.collection; -import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -70,11 +69,11 @@ import org.hibernate.mapping.Column; import org.hibernate.mapping.Formula; import org.hibernate.mapping.IdentifierCollection; import org.hibernate.mapping.IndexedCollection; -import org.hibernate.mapping.List; import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Table; import org.hibernate.mapping.Value; import org.hibernate.metadata.CollectionMetadata; +import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.PluralAttributeMapping; @@ -146,11 +145,14 @@ import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER */ @Internal public abstract class AbstractCollectionPersister - implements SQLLoadableCollection, PluralAttributeMappingImpl.Aware, CollectionMutationTarget, CollectionMetadata { + implements CollectionPersister, CollectionMutationTarget, PluralAttributeMappingImpl.Aware, DeprecatedCollectionStuff { private final NavigableRole navigableRole; private final CollectionSemantics collectionSemantics; + private final EntityPersister ownerPersister; + private final SessionFactoryImplementor factory; + protected final String qualifiedTableName; private final CollectionTableMapping tableMapping; private final String sqlSelectSizeString; @@ -164,19 +166,11 @@ public abstract class AbstractCollectionPersister private final boolean hasOrder; private final boolean hasManyToManyOrder; - private final int baseIndex; - private final String mappedByProperty; protected final boolean indexContainsFormula; protected final boolean elementIsPureFormula; - // types - private final Type keyType; - private final Type indexType; - protected final Type elementType; - private final Type identifierType; - // columns protected final String[] keyColumnNames; protected final String[] indexColumnNames; @@ -192,21 +186,12 @@ public abstract class AbstractCollectionPersister protected final String[] elementFormulas; protected final boolean[] elementColumnIsGettable; protected final boolean[] elementColumnIsSettable; - protected final String[] indexColumnAliases; - protected final String[] elementColumnAliases; - protected final String[] keyColumnAliases; protected final String identifierColumnName; - private final String identifierColumnAlias; - - protected final String qualifiedTableName; private final String queryLoaderName; private final boolean isPrimitiveArray; - private final boolean isArray; - protected final boolean hasIndex; - protected final boolean hasIdentifier; private final boolean isLazy; private final boolean isExtraLazy; protected final boolean isInverse; @@ -219,17 +204,13 @@ public abstract class AbstractCollectionPersister // extra information about the element type private final Class elementClass; - private final String entityName; private final Dialect dialect; protected final SqlExceptionHelper sqlExceptionHelper; - private final SessionFactoryImplementor factory; - private final EntityPersister ownerPersister; private final BeforeExecutionGenerator identifierGenerator; private final PropertyMapping elementPropertyMapping; private final EntityPersister elementPersister; private final CollectionDataAccess cacheAccessStrategy; - private final CollectionType collectionType; private final CacheEntryStructure cacheEntryStructure; @@ -244,8 +225,6 @@ public abstract class AbstractCollectionPersister private final String[] spaces; - private final Map collectionPropertyColumnAliases = new HashMap<>(); - private final Comparator comparator; private CollectionLoader collectionLoader; @@ -267,10 +246,12 @@ public abstract class AbstractCollectionPersister Collection collectionBootDescriptor, CollectionDataAccess cacheAccessStrategy, RuntimeModelCreationContext creationContext) throws MappingException, CacheException { - - final Value elementBootDescriptor = collectionBootDescriptor.getElement(); - this.factory = creationContext.getSessionFactory(); + this.collectionSemantics = creationContext.getBootstrapContext() + .getMetadataBuildingOptions() + .getPersistentCollectionRepresentationResolver() + .resolveRepresentation( collectionBootDescriptor ); + this.cacheAccessStrategy = cacheAccessStrategy; if ( creationContext.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) { cacheEntryStructure = collectionBootDescriptor.isMap() @@ -285,19 +266,19 @@ public abstract class AbstractCollectionPersister sqlExceptionHelper = creationContext.getJdbcServices().getSqlExceptionHelper(); collectionType = collectionBootDescriptor.getCollectionType(); navigableRole = new NavigableRole( collectionBootDescriptor.getRole() ); - entityName = collectionBootDescriptor.getOwnerEntityName(); - ownerPersister = creationContext.getDomainModel().getEntityDescriptor( entityName ); + ownerPersister = creationContext.getDomainModel().getEntityDescriptor( collectionBootDescriptor.getOwnerEntityName() ); queryLoaderName = collectionBootDescriptor.getLoaderName(); isMutable = collectionBootDescriptor.isMutable(); mappedByProperty = collectionBootDescriptor.getMappedByProperty(); - Table table = collectionBootDescriptor.getCollectionTable(); + final Value elementBootDescriptor = collectionBootDescriptor.getElement(); + final Table table = collectionBootDescriptor.getCollectionTable(); + fetchMode = elementBootDescriptor.getFetchMode(); elementType = elementBootDescriptor.getType(); // isSet = collectionBinding.isSet(); // isSorted = collectionBinding.isSorted(); isPrimitiveArray = collectionBootDescriptor.isPrimitiveArray(); - isArray = collectionBootDescriptor.isArray(); subselectLoadable = collectionBootDescriptor.isSubselectLoadable(); qualifiedTableName = determineTableName( table ); @@ -420,7 +401,7 @@ public abstract class AbstractCollectionPersister // INDEX AND ROW SELECT - hasIndex = collectionBootDescriptor.isIndexed(); + final boolean hasIndex = collectionBootDescriptor.isIndexed(); if ( hasIndex ) { // NativeSQL: collect index column and auto-aliases IndexedCollection indexedCollection = (IndexedCollection) collectionBootDescriptor; @@ -469,10 +450,6 @@ public abstract class AbstractCollectionPersister i++; } indexContainsFormula = hasFormula; - //noinspection ConstantConditions - baseIndex = indexedCollection.isList() - ? ( (List) indexedCollection ).getBaseIndex() - : 0; } else { indexContainsFormula = false; @@ -483,10 +460,9 @@ public abstract class AbstractCollectionPersister indexType = null; indexColumnNames = null; indexColumnAliases = null; - baseIndex = 0; } - hasIdentifier = collectionBootDescriptor.isIdentified(); + final boolean hasIdentifier = collectionBootDescriptor.isIdentified(); if ( hasIdentifier ) { if ( collectionBootDescriptor.isOneToMany() ) { throw new MappingException( "one-to-many collections with identifiers are not supported" ); @@ -588,11 +564,6 @@ public abstract class AbstractCollectionPersister // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // "mapping model" - this.collectionSemantics = creationContext.getBootstrapContext() - .getMetadataBuildingOptions() - .getPersistentCollectionRepresentationResolver() - .resolveRepresentation( collectionBootDescriptor ); - if ( queryLoaderName != null ) { final NamedQueryMemento namedQueryMemento = factory .getQueryEngine() @@ -626,11 +597,6 @@ public abstract class AbstractCollectionPersister return navigableRole; } - @Override - public String getRole() { - return navigableRole.getFullPath(); - } - @Override public Comparator getSortingComparator() { return comparator; @@ -655,7 +621,6 @@ public abstract class AbstractCollectionPersister if ( attributeMapping.getIndexDescriptor() != null ) { collectionElementLoaderByIndex = new CollectionElementLoaderByIndex( attributeMapping, - baseIndex, LoadQueryInfluencers.NONE, getFactory() ); @@ -793,11 +758,6 @@ public abstract class AbstractCollectionPersister return cacheAccessStrategy != null; } - @Override - public CollectionType getCollectionType() { - return collectionType; - } - protected abstract RowMutationOperations getRowMutationOperations(); protected abstract RemoveCoordinator getRemoveCoordinator(); @@ -839,21 +799,6 @@ public abstract class AbstractCollectionPersister return hasWhere; } - @Override - public Type getKeyType() { - return keyType; - } - - @Override - public Type getIndexType() { - return indexType; - } - - @Override - public Type getElementType() { - return elementType; - } - /** * Return the element class of an array, or null otherwise. needed by arrays */ @@ -868,14 +813,16 @@ public abstract class AbstractCollectionPersister @Deprecated(forRemoval = true) @Remove protected Object decrementIndexByBase(Object index) { - if ( baseIndex != 0 ) { + final int baseIndex = attributeMapping.getIndexMetadata().getListIndexBase(); + if ( baseIndex > 0 ) { index = (Integer)index - baseIndex; } return index; } protected Object incrementIndexByBase(Object index) { - if ( baseIndex != 0 ) { + final int baseIndex = attributeMapping.getIndexMetadata().getListIndexBase(); + if ( baseIndex > 0 ) { index = (Integer)index + baseIndex; } return index; @@ -888,12 +835,12 @@ public abstract class AbstractCollectionPersister @Override public boolean isArray() { - return isArray; + return collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY; } @Override public String getIdentifierColumnName() { - if ( hasIdentifier ) { + if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ID_BAG ) { return identifierColumnName; } else { @@ -950,7 +897,7 @@ public abstract class AbstractCollectionPersister i++; } - if ( hasIndex ) { + if ( hasIndex() ) { for ( String indexAlias : indexColumnAliases ) { sqlSelections.set( i, @@ -963,7 +910,7 @@ public abstract class AbstractCollectionPersister i++; } } - if ( hasIdentifier ) { + if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ID_BAG ) { sqlSelections.set( i, new SqlSelectionImpl( @@ -1088,7 +1035,7 @@ public abstract class AbstractCollectionPersister @Override public boolean hasIndex() { - return hasIndex; + return collectionSemantics.getCollectionClassification().isIndexed(); } @Override @@ -1125,7 +1072,7 @@ public abstract class AbstractCollectionPersister } public String getOwnerEntityName() { - return entityName; + return ownerPersister.getEntityName(); } @Override @@ -1143,11 +1090,6 @@ public abstract class AbstractCollectionPersister return identifierGenerator; } - @Override - public Type getIdentifierType() { - return identifierType; - } - @Override public boolean hasOrphanDelete() { return hasOrphanDelete; @@ -1410,10 +1352,10 @@ public abstract class AbstractCollectionPersister initCollectionPropertyMap( "key", keyType, keyColumnAliases ); initCollectionPropertyMap( "element", elementType, elementColumnAliases ); - if ( hasIndex ) { + if ( hasIndex() ) { initCollectionPropertyMap( "index", indexType, indexColumnAliases ); } - if ( hasIdentifier ) { + if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ID_BAG ) { initCollectionPropertyMap( "id", identifierType, new String[] { identifierColumnAlias } ); } } @@ -1445,6 +1387,7 @@ public abstract class AbstractCollectionPersister getKeyType().nullSafeSet( st, key, 1, session ); ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st ); try { + final int baseIndex = Math.max( attributeMapping.getIndexMetadata().getListIndexBase(), 0 ); return rs.next() ? rs.getInt( 1 ) - baseIndex : 0; } finally { @@ -1617,7 +1560,7 @@ public abstract class AbstractCollectionPersister @Override public boolean hasPhysicalIndexColumn() { - return hasIndex && !indexContainsFormula; + return hasIndex() && !indexContainsFormula; } @Override @@ -1791,6 +1734,56 @@ public abstract class AbstractCollectionPersister + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Types (the methods are already deprecated on CollectionPersister) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Deprecated private final CollectionType collectionType; + @Deprecated private final Type keyType; + @Deprecated private final Type identifierType; + @Deprecated private final Type indexType; + @Deprecated protected final Type elementType; + + public CollectionType getCollectionType() { + return collectionType; + } + + @Override + public Type getKeyType() { + return keyType; + } + + @Override + public Type getIdentifierType() { + return identifierType; + } + + @Override + public Type getIndexType() { + return indexType; + } + + @Override + public Type getElementType() { + return elementType; + } + + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State related to this we handle differently in 6+. In other words, state + // that is no longer needed + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Deprecated protected final String[] keyColumnAliases; + @Deprecated private final String identifierColumnAlias; + @Deprecated protected final String[] indexColumnAliases; + @Deprecated protected final String[] elementColumnAliases; + @Deprecated private final Map collectionPropertyColumnAliases = new HashMap<>(); @Override public String[] getKeyColumnAliases(String suffix) { @@ -1804,7 +1797,7 @@ public abstract class AbstractCollectionPersister @Override public String[] getIndexColumnAliases(String suffix) { - if ( hasIndex ) { + if ( hasIndex() ) { return new Alias( suffix ).toAliasStrings( indexColumnAliases ); } else { @@ -1814,7 +1807,7 @@ public abstract class AbstractCollectionPersister @Override public String getIdentifierColumnAlias(String suffix) { - if ( hasIdentifier ) { + if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ID_BAG ) { return new Alias( suffix ).toAliasString( identifierColumnAlias ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java index 553f276152..fc8ddbcd90 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java @@ -640,7 +640,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { else { deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getKeyDescriptor().getKeyPart() ); - if ( hasIndex && !indexContainsFormula ) { + if ( hasIndex() && !indexContainsFormula ) { assert pluralAttribute.getIndexDescriptor() != null; deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIndexDescriptor() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/CollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/CollectionPersister.java index 282b3715d6..2e9b0ba914 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/CollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/CollectionPersister.java @@ -80,15 +80,24 @@ import org.hibernate.type.Type; * * * - * @see QueryableCollection * @see PersistentCollection + * @see PluralAttributeMapping * * @author Gavin King */ public interface CollectionPersister extends Restrictable { + /** + * The NavigableRole for this collection. + */ NavigableRole getNavigableRole(); - String getRole(); + default String getRole() { + return getNavigableRole().getFullPath(); + } + + default PluralAttributeMapping getAttributeMapping() { + throw new UnsupportedOperationException( "CollectionPersister used for [" + getRole() + "] does not support SQL AST" ); + } /** * Get the persister of the entity that "owns" this collection @@ -123,22 +132,6 @@ public interface CollectionPersister extends Restrictable { */ CacheEntryStructure getCacheEntryStructure(); - /** - * Get the associated {@code Type} - */ - CollectionType getCollectionType(); - /** - * Get the "key" type (the type of the foreign key) - */ - Type getKeyType(); - /** - * Get the "index" type for a list or map (optional operation) - */ - Type getIndexType(); - /** - * Get the "element" type - */ - Type getElementType(); /** * Return the element class of an array, or null otherwise */ @@ -245,11 +238,6 @@ public interface CollectionPersister extends Restrictable { return getIdentifierGenerator(); } - /** - * Get the type of the surrogate key - */ - Type getIdentifierType(); - /** * Does this collection implement "orphan delete"? */ @@ -302,10 +290,6 @@ public interface CollectionPersister extends Restrictable { boolean isAffectedByEnabledFilters(SharedSessionContractImplementor session); - default PluralAttributeMapping getAttributeMapping() { - throw new UnsupportedOperationException( "CollectionPersister used for [" + getRole() + "] does not support SQL AST" ); - } - default boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) { throw new UnsupportedOperationException( "CollectionPersister used for [" + getRole() + "] does not support SQL AST" ); } @@ -408,4 +392,54 @@ public interface CollectionPersister extends Restrictable { */ @Deprecated( since = "6", forRemoval = true ) String getIdentifierColumnAlias(String suffix); + + /** + * Get the associated {@code Type} + * + * @deprecated Hibernate is moving away from {@link Type}. Corresponding + * {@linkplain org.hibernate.metamodel.mapping mapping metamodel} calls should + * be used instead - here (generally), {@link PluralAttributeMapping} + */ + @Deprecated( forRemoval = true ) + CollectionType getCollectionType(); + + /** + * Get the "key" type (the type of the foreign key) + * + * @deprecated Hibernate is moving away from {@link Type}. Corresponding + * {@linkplain org.hibernate.metamodel.mapping mapping metamodel} calls should + * be used instead - here, {@link PluralAttributeMapping#getKeyDescriptor()} + */ + @Deprecated( forRemoval = true ) + Type getKeyType(); + + /** + * Get the "index" type for a list or map (optional operation) + * + * @deprecated Hibernate is moving away from {@link Type}. Corresponding + * {@linkplain org.hibernate.metamodel.mapping mapping metamodel} calls should + * be used instead - here, {@link PluralAttributeMapping#getIndexDescriptor()} + */ + @Deprecated( forRemoval = true ) + Type getIndexType(); + + /** + * Get the "element" type + * + * @deprecated Hibernate is moving away from {@link Type}. Corresponding + * {@linkplain org.hibernate.metamodel.mapping mapping metamodel} calls should + * be used instead - here, {@link PluralAttributeMapping#getElementDescriptor()} + */ + @Deprecated( forRemoval = true ) + Type getElementType(); + + /** + * Get the type of the surrogate key + * + * @deprecated Hibernate is moving away from {@link Type}. Corresponding + * {@linkplain org.hibernate.metamodel.mapping mapping metamodel} calls should + * be used instead - here, {@link PluralAttributeMapping#getIdentifierDescriptor()} + */ + @Deprecated( forRemoval = true ) + Type getIdentifierType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/DeprecatedCollectionStuff.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/DeprecatedCollectionStuff.java new file mode 100644 index 0000000000..aaf41e5499 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/DeprecatedCollectionStuff.java @@ -0,0 +1,20 @@ +/* + * 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.persister.collection; + +import org.hibernate.metadata.CollectionMetadata; + +/** + * @deprecated Just used to singly extend all the deprecated collection persister roles + */ +@Deprecated +public interface DeprecatedCollectionStuff extends SQLLoadableCollection, CollectionMetadata { + @Override + default String getRole() { + return SQLLoadableCollection.super.getRole(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index 6fdd96be50..aac2db7f90 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -213,7 +213,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { // If one-to-many and inverse, still need to create the index. See HHH-5732. final boolean doWrite = isInverse - && hasIndex + && hasIndex() && !indexContainsFormula && ArrayHelper.countTrue( indexColumnIsSettable ) > 0; if ( !doWrite ) { @@ -328,7 +328,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { assert fkDescriptor != null; final int keyColumnCount = fkDescriptor.getJdbcTypeCount(); - final int valuesCount = hasIndex + final int valuesCount = hasIndex() ? keyColumnCount + indexColumnNames.length : keyColumnCount; @@ -360,7 +360,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { ); } - if ( hasIndex && !indexContainsFormula ) { + if ( hasIndex() && !indexContainsFormula ) { getAttributeMapping().getIndexDescriptor().forEachSelectable( (selectionIndex, selectableMapping) -> { if ( ! selectableMapping.isUpdateable() ) { return; @@ -402,7 +402,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { final RowMutationOperations.Values writeIndexValues; final RowMutationOperations.Restrictions writeIndexRestrictions; final boolean needsWriteIndex = isInverse - && hasIndex + && hasIndex() && !indexContainsFormula && !ArrayHelper.isAllFalse( indexColumnIsSettable ); if ( needsWriteIndex ) { @@ -592,7 +592,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { } // set the value for each index column to null - if ( hasIndex && !indexContainsFormula ) { + if ( hasIndex() && !indexContainsFormula ) { final CollectionPart indexDescriptor = getAttributeMapping().getIndexDescriptor(); assert indexDescriptor != null; 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 3764b39561..1554dffe62 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 @@ -309,20 +309,15 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere */ @Internal public abstract class AbstractEntityPersister - implements OuterJoinLoadable, ClassMetadata, UniqueKeyLoadable, - SQLLoadable, LazyPropertyInitializer, PostInsertIdentityPersister, Lockable, - org.hibernate.persister.entity.Queryable, InFlightEntityMappingType, EntityMutationTarget { + implements InFlightEntityMappingType, EntityMutationTarget, LazyPropertyInitializer, PostInsertIdentityPersister, DeprecatedEntityStuff { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractEntityPersister.class ); public static final String ENTITY_CLASS = "class"; public static final String VERSION_COLUMN_ALIAS = "version_"; - private final SessionFactoryImplementor factory; - private final NavigableRole navigableRole; - - private final EntityMetamodel entityMetamodel; + private final SessionFactoryImplementor factory; private final EntityEntryFactory entityEntryFactory; private final String sqlAliasStem; @@ -332,18 +327,6 @@ public abstract class AbstractEntityPersister private NaturalIdLoader naturalIdLoader; private MultiNaturalIdLoader multiNaturalIdLoader; - private SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy; - private SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy; - - private final EntityDataAccess cacheAccessStrategy; - private final NaturalIdDataAccess naturalIdRegionAccessStrategy; - private final CacheEntryHelper cacheEntryHelper; - private final boolean canReadFromCache; - private final boolean canWriteToCache; - private final boolean invalidateCache; - private final boolean isLazyPropertiesCacheable; - private final boolean useReferenceCacheEntries; - private final String[] rootTableKeyColumnNames; private final String[] rootTableKeyColumnReaders; private final String[] rootTableKeyColumnReaderTemplates; @@ -392,47 +375,39 @@ public abstract class AbstractEntityPersister private final boolean[] propertyDefinedOnSubclass; private final CascadeStyle[] subclassPropertyCascadeStyleClosure; - //information about all columns/formulas in class hierarchy - private final String[] subclassColumnAliasClosure; - private final String[] subclassFormulaAliasClosure; - - // dynamic filters attached to the class-level - private final FilterHelper filterHelper; - private volatile Set affectingFetchProfileNames; - + private Map lazyLoadPlanByFetchGroup; private final LockModeEnumMap lockers = new LockModeEnumMap<>(); + private String sqlVersionSelectString; private EntityTableMapping[] tableMappings; private InsertCoordinator insertCoordinator; private UpdateCoordinator updateCoordinator; private DeleteCoordinator deleteCoordinator; - protected Expectation[] insertExpectations; - protected Expectation[] updateExpectations; - protected Expectation[] deleteExpectations; + private SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy; + private SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy; - // SQL strings - private String sqlVersionSelectString; - private Map lazyLoadPlanByFetchGroup; + private final EntityDataAccess cacheAccessStrategy; + private final NaturalIdDataAccess naturalIdRegionAccessStrategy; + private final CacheEntryHelper cacheEntryHelper; + private final boolean canReadFromCache; + private final boolean canWriteToCache; + private final boolean invalidateCache; + private final boolean isLazyPropertiesCacheable; + private final boolean useReferenceCacheEntries; + // dynamic filters attached to the class-level + private final FilterHelper filterHelper; + private volatile Set affectingFetchProfileNames; private GeneratedValuesProcessor insertGeneratedValuesProcessor; private GeneratedValuesProcessor updateGeneratedValuesProcessor; - //Custom SQL (would be better if these were private) - protected boolean[] insertCallable; - protected boolean[] updateCallable; - protected boolean[] deleteCallable; - protected String[] customSQLInsert; - protected String[] customSQLUpdate; - protected String[] customSQLDelete; - private InsertGeneratedIdentifierDelegate identityDelegate; private String identitySelectString; private boolean[] tableHasColumns; - private final Map subclassPropertyAliases = new HashMap<>(); private final Map subclassPropertyColumnNames = new HashMap<>(); private final JavaType javaType; @@ -455,7 +430,6 @@ public abstract class AbstractEntityPersister protected ReflectionOptimizer.AccessOptimizer accessOptimizer; -// private final String[] fullDiscriminatorSQLValues; private final Object[] fullDiscriminatorValues; /** @@ -938,10 +912,6 @@ public abstract class AbstractEntityPersister : Template.TEMPLATE + "." + DISCRIMINATOR_ALIAS; } - public String getDiscriminatorAlias() { - return DISCRIMINATOR_ALIAS; - } - public String getDiscriminatorFormulaTemplate() { return null; } @@ -2468,136 +2438,12 @@ public abstract class AbstractEntityPersister ); } - // returns the aliases of the selectable columns - protected String[] getSubclassColumnAliasClosure() { - return subclassColumnAliasClosure; - } - - protected String[] getSubclassFormulaAliasClosure() { - return subclassFormulaAliasClosure; - } - - @Override - public String[] getSubclassPropertyColumnAliases(String propertyName, String suffix) { - final String[] rawAliases = subclassPropertyAliases.get( propertyName ); - if ( rawAliases == null ) { - return null; - } - else { - final String[] result = new String[rawAliases.length]; - for ( int i = 0; i < rawAliases.length; i++ ) { - result[i] = new Alias( suffix ).toUnquotedAliasString( rawAliases[i] ); - } - return result; - } - } - @Override public String[] getSubclassPropertyColumnNames(String propertyName) { //TODO: should we allow suffixes on these ? return subclassPropertyColumnNames.get( propertyName ); } - - //This is really ugly, but necessary: - - /** - * Must be called by subclasses, at the end of their constructors - */ - protected void initSubclassPropertyAliasesMap(PersistentClass model) throws MappingException { - - // ALIASES - internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosure() ); - - // aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id' - if ( !entityMetamodel.hasNonIdentifierPropertyNamedId() ) { - subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() ); - subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() ); - } - - // aliases named identifier ( alias.idname ) - if ( hasIdentifierProperty() ) { - subclassPropertyAliases.put( getIdentifierPropertyName(), getIdentifierAliases() ); - subclassPropertyColumnNames.put( getIdentifierPropertyName(), getIdentifierColumnNames() ); - } - - // aliases for composite-id's - if ( getIdentifierType().isComponentType() ) { - // Fetch embedded identifiers property names from the "virtual" identifier component - final CompositeType componentId = (CompositeType) getIdentifierType(); - final String[] idPropertyNames = componentId.getPropertyNames(); - final String[] idAliases = getIdentifierAliases(); - final String[] idColumnNames = getIdentifierColumnNames(); - - for ( int i = 0; i < idPropertyNames.length; i++ ) { - if ( entityMetamodel.hasNonIdentifierPropertyNamedId() ) { - subclassPropertyAliases.put( - ENTITY_ID + "." + idPropertyNames[i], - new String[] {idAliases[i]} - ); - subclassPropertyColumnNames.put( - ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyNames[i], - new String[] {idColumnNames[i]} - ); - } -// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyNames() ) ) { - if ( hasIdentifierProperty() ) { - subclassPropertyAliases.put( - getIdentifierPropertyName() + "." + idPropertyNames[i], - new String[] {idAliases[i]} - ); - subclassPropertyColumnNames.put( - getIdentifierPropertyName() + "." + idPropertyNames[i], - new String[] {idColumnNames[i]} - ); - } - else { - // embedded composite ids ( alias.idName1, alias.idName2 ) - subclassPropertyAliases.put( idPropertyNames[i], new String[] {idAliases[i]} ); - subclassPropertyColumnNames.put( idPropertyNames[i], new String[] {idColumnNames[i]} ); - } - } - } - - if ( entityMetamodel.isPolymorphic() ) { - subclassPropertyAliases.put( ENTITY_CLASS, new String[] {getDiscriminatorAlias()} ); - subclassPropertyColumnNames.put( ENTITY_CLASS, new String[] {getDiscriminatorColumnName()} ); - } - - } - - private void internalInitSubclassPropertyAliasesMap(String path, List properties) { - for (Property property : properties) { - final String name = path == null ? property.getName() : path + "." + property.getName(); - if ( property.isComposite() ) { - Component component = (Component) property.getValue(); - internalInitSubclassPropertyAliasesMap( name, component.getProperties() ); - } - - String[] aliases = new String[property.getColumnSpan()]; - String[] cols = new String[property.getColumnSpan()]; - int l = 0; - for ( Selectable selectable: property.getSelectables() ) { - Dialect dialect = getFactory().getJdbcServices().getDialect(); - aliases[l] = selectable.getAlias( dialect, property.getValue().getTable() ); - cols[l] = selectable.getText(dialect); // TODO: skip formulas? - l++; - } - - subclassPropertyAliases.put( name, aliases ); - subclassPropertyColumnNames.put( name, cols ); - } - - } - - /** - * Called by Hibernate Reactive - */ - @SuppressWarnings("unused") - protected String[][] getLazyPropertyColumnAliases() { - return lazyPropertyColumnAliases; - } - @Override public Object loadByUniqueKey( String propertyName, @@ -5954,8 +5800,13 @@ public abstract class AbstractEntityPersister return hasPartitionedSelectionMapping; } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Deprecations + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * @deprecated With no replacement @@ -6252,4 +6103,193 @@ public abstract class AbstractEntityPersister } return true; } + + + + + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State built and stored here during instantiation, and only used in other + // phases of initialization + // - postConstruct + // - postInstantiate + // - prepareMappingModel + // - ... + // + // This is effectively bootstrap state that is kept around during runtime. + // + // Would be better to encapsulate and store this state relative to the + // `PersisterCreationContext` so it can get released after bootstrap + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Deprecated protected Expectation[] insertExpectations; + @Deprecated protected Expectation[] updateExpectations; + @Deprecated protected Expectation[] deleteExpectations; + + @Deprecated protected boolean[] insertCallable; + @Deprecated protected boolean[] updateCallable; + @Deprecated protected boolean[] deleteCallable; + + @Deprecated protected String[] customSQLInsert; + @Deprecated protected String[] customSQLUpdate; + @Deprecated protected String[] customSQLDelete; + + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // State related to this we handle differently in 6+. In other words, state + // that is no longer needed + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Deprecated private final EntityMetamodel entityMetamodel; + + @Deprecated private final String[] subclassColumnAliasClosure; + @Deprecated private final String[] subclassFormulaAliasClosure; + @Deprecated private final Map subclassPropertyAliases = new HashMap<>(); + + /** + * @deprecated Hibernate no longer uses aliases to read from result sets + */ + @Deprecated protected String[] getSubclassColumnAliasClosure() { + return subclassColumnAliasClosure; + } + + /** + * @deprecated Hibernate no longer uses aliases to read from result sets + */ + @Deprecated protected String[] getSubclassFormulaAliasClosure() { + return subclassFormulaAliasClosure; + } + + /** + * @deprecated Hibernate no longer uses aliases to read from result sets + */ + @Deprecated @Override + public String[] getSubclassPropertyColumnAliases(String propertyName, String suffix) { + final String[] rawAliases = subclassPropertyAliases.get( propertyName ); + if ( rawAliases == null ) { + return null; + } + else { + final String[] result = new String[rawAliases.length]; + for ( int i = 0; i < rawAliases.length; i++ ) { + result[i] = new Alias( suffix ).toUnquotedAliasString( rawAliases[i] ); + } + return result; + } + } + + /** + * Must be called by subclasses, at the end of their constructors + * + * @deprecated Hibernate no longer uses aliases to read from result sets + */ + @Deprecated protected void initSubclassPropertyAliasesMap(PersistentClass model) throws MappingException { + + // ALIASES + internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosure() ); + + // aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id' + if ( !entityMetamodel.hasNonIdentifierPropertyNamedId() ) { + subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() ); + subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() ); + } + + // aliases named identifier ( alias.idname ) + if ( hasIdentifierProperty() ) { + subclassPropertyAliases.put( getIdentifierPropertyName(), getIdentifierAliases() ); + subclassPropertyColumnNames.put( getIdentifierPropertyName(), getIdentifierColumnNames() ); + } + + // aliases for composite-id's + if ( getIdentifierType().isComponentType() ) { + // Fetch embedded identifiers property names from the "virtual" identifier component + final CompositeType componentId = (CompositeType) getIdentifierType(); + final String[] idPropertyNames = componentId.getPropertyNames(); + final String[] idAliases = getIdentifierAliases(); + final String[] idColumnNames = getIdentifierColumnNames(); + + for ( int i = 0; i < idPropertyNames.length; i++ ) { + if ( entityMetamodel.hasNonIdentifierPropertyNamedId() ) { + subclassPropertyAliases.put( + ENTITY_ID + "." + idPropertyNames[i], + new String[] {idAliases[i]} + ); + subclassPropertyColumnNames.put( + ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyNames[i], + new String[] {idColumnNames[i]} + ); + } +// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyNames() ) ) { + if ( hasIdentifierProperty() ) { + subclassPropertyAliases.put( + getIdentifierPropertyName() + "." + idPropertyNames[i], + new String[] {idAliases[i]} + ); + subclassPropertyColumnNames.put( + getIdentifierPropertyName() + "." + idPropertyNames[i], + new String[] {idColumnNames[i]} + ); + } + else { + // embedded composite ids ( alias.idName1, alias.idName2 ) + subclassPropertyAliases.put( idPropertyNames[i], new String[] {idAliases[i]} ); + subclassPropertyColumnNames.put( idPropertyNames[i], new String[] {idColumnNames[i]} ); + } + } + } + + if ( entityMetamodel.isPolymorphic() ) { + subclassPropertyAliases.put( ENTITY_CLASS, new String[] {getDiscriminatorAlias()} ); + subclassPropertyColumnNames.put( ENTITY_CLASS, new String[] {getDiscriminatorColumnName()} ); + } + + } + + private void internalInitSubclassPropertyAliasesMap(String path, List properties) { + for (Property property : properties) { + final String name = path == null ? property.getName() : path + "." + property.getName(); + if ( property.isComposite() ) { + Component component = (Component) property.getValue(); + internalInitSubclassPropertyAliasesMap( name, component.getProperties() ); + } + + String[] aliases = new String[property.getColumnSpan()]; + String[] cols = new String[property.getColumnSpan()]; + int l = 0; + for ( Selectable selectable: property.getSelectables() ) { + Dialect dialect = getFactory().getJdbcServices().getDialect(); + aliases[l] = selectable.getAlias( dialect, property.getValue().getTable() ); + cols[l] = selectable.getText(dialect); // TODO: skip formulas? + l++; + } + + subclassPropertyAliases.put( name, aliases ); + subclassPropertyColumnNames.put( name, cols ); + } + + } + + /** + * Called by Hibernate Reactive + * + * @deprecated Hibernate no longer uses aliases to read from result sets + */ + @Deprecated @SuppressWarnings("unused") + protected String[][] getLazyPropertyColumnAliases() { + return lazyPropertyColumnAliases; + } + + /** + * @deprecated Hibernate no longer uses aliases to read from result sets + */ + @Deprecated + public String getDiscriminatorAlias() { + return DISCRIMINATOR_ALIAS; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DeprecatedEntityStuff.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DeprecatedEntityStuff.java new file mode 100644 index 0000000000..e3a42a8e68 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DeprecatedEntityStuff.java @@ -0,0 +1,17 @@ +/* + * 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.persister.entity; + +import org.hibernate.metadata.ClassMetadata; + +/** + * @deprecated Just used to singly extend all the deprecated entity persister roles + */ +@Deprecated +public interface DeprecatedEntityStuff + extends OuterJoinLoadable, ClassMetadata, UniqueKeyLoadable, SQLLoadable, Lockable, org.hibernate.persister.entity.Queryable { +} 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 66b8cdbfed..60d53b2ee9 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 @@ -590,6 +590,14 @@ public interface EntityPersister extends EntityMappingType, RootTableGroupProduc */ List multiLoad(Object[] ids, EventSource session, MultiIdLoadOptions loadOptions); + @Override + default Object loadByUniqueKey(String propertyName, Object uniqueKey, SharedSessionContractImplementor session) { + throw new UnsupportedOperationException( + "EntityPersister implementation '" + getClass().getName() + + "' does not support 'UniqueKeyLoadable'" + ); + } + /** * Do a version check (optional operation) */ diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 3bfe40b33e..ad9513c2de 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -113,7 +113,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private final String discriminatorColumnReaders; private final String discriminatorColumnReaderTemplate; private final String discriminatorFormulaTemplate; - private final String discriminatorAlias; private final BasicType discriminatorType; private final Object discriminatorValue; private final String discriminatorSQLValue; @@ -122,11 +121,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { private final String[] constraintOrderedTableNames; private final String[][] constraintOrderedKeyColumnNames; - //private final Map propertyTableNumbersByName = new HashMap(); -// private final Map propertyTableNumbersByNameAndSubclass; - - //INITIALIZATION: - @Deprecated(since = "6.0") public SingleTableEntityPersister( final PersistentClass persistentClass, @@ -321,7 +315,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { discriminatorInsertable = isDiscriminatorInsertable( persistentClass ); if ( discriminator.hasFormula() ) { final Formula formula = (Formula) selectable; -// discriminatorFormula = formula.getFormula(); discriminatorFormulaTemplate = formula.getTemplate( dialect, typeConfiguration, functionRegistry ); discriminatorColumnName = null; discriminatorColumnReaders = null; @@ -334,7 +327,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { discriminatorColumnReaders = column.getReadExpr( dialect ); discriminatorColumnReaderTemplate = column.getTemplate( dialect, typeConfiguration, functionRegistry ); discriminatorAlias = column.getAlias( dialect, persistentClass.getRootTable() ); -// discriminatorFormula = null; discriminatorFormulaTemplate = null; } } @@ -452,11 +444,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { return discriminatorColumnReaderTemplate; } - @Override - public String getDiscriminatorAlias() { - return discriminatorAlias; - } - @Override public String getDiscriminatorFormulaTemplate() { return discriminatorFormulaTemplate; @@ -748,4 +735,17 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { ); } } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Deprecations + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Deprecated private final String discriminatorAlias; + + @Override + public String getDiscriminatorAlias() { + return discriminatorAlias; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UniqueKeyLoadable.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UniqueKeyLoadable.java index 9c7a11a5b6..76081a16cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UniqueKeyLoadable.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UniqueKeyLoadable.java @@ -12,7 +12,10 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; * An {@link EntityPersister} that can be loaded by a non-primary unique key. * * @author Gavin King + * + * @deprecated Use {@link org.hibernate.metamodel.mapping.EntityMappingType#loadByUniqueKey} instead */ +@Deprecated public interface UniqueKeyLoadable extends Loadable { /** * Load an instance of the persistent class, by a unique key other diff --git a/hibernate-core/src/main/java/org/hibernate/persister/package-info.java b/hibernate-core/src/main/java/org/hibernate/persister/package-info.java index dfcd34d280..f1c8672a5f 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/package-info.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/package-info.java @@ -16,5 +16,12 @@ * defines a mechanism for persisting instances of a given * collection role. *

+ * + * @apiNote This package is considered an SPI, meaning it is intended for use + * by internal code and by integrations. It is not supported for application use. + * Be aware that its backwards compatibility guarantee is tied defined by SPI which + * is less strict than API, which is intended for application use (things + * like {@link org.hibernate.SessionFactory}, {@link org.hibernate.Session}, + * {@link org.hibernate.Transaction}, etc.). */ package org.hibernate.persister; diff --git a/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java b/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java index 7a67894ce8..053651adaa 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java +++ b/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java @@ -674,6 +674,11 @@ public class AnonymousTupleEntityValuedModelPart delegate.getEntityMappingType().visitConstraintOrderedTables( consumer ); } + @Override + public Object loadByUniqueKey(String propertyName, Object uniqueKey, SharedSessionContractImplementor session) { + return delegate.getEntityMappingType().loadByUniqueKey( propertyName, uniqueKey, session ); + } + @Override public NaturalIdLoader getNaturalIdLoader() { return delegate.getEntityMappingType().getNaturalIdLoader(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java index 96a50015f7..d1e111030c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java @@ -17,7 +17,6 @@ import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; @@ -147,7 +146,7 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp && isEnhancedForLazyLoading( parentEntityInitializer ) ) { return; } - entityInstance = ( (UniqueKeyLoadable) concreteDescriptor ).loadByUniqueKey( + entityInstance = concreteDescriptor.loadByUniqueKey( uniqueKeyPropertyName, identifier, session diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java index 3ba3bd54ae..66871a4914 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java @@ -11,7 +11,6 @@ import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.FetchParentAccess; @@ -83,7 +82,7 @@ public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchIn final JdbcValuesSourceProcessingState jdbcValuesSourceProcessingState = rowProcessingState.getJdbcValuesSourceProcessingState(); jdbcValuesSourceProcessingState.registerInitializer( euk, this ); - entityInstance = ( (UniqueKeyLoadable) concreteDescriptor ).loadByUniqueKey( + entityInstance = concreteDescriptor.loadByUniqueKey( uniqueKeyPropertyName, entityIdentifier, session diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java index e70b718159..b44931b1d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java @@ -13,11 +13,9 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityUniqueKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; @@ -208,7 +206,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch { ); Object entityInstance = persistenceContext.getEntity( euk ); if ( entityInstance == null ) { - entityInstance = ( (UniqueKeyLoadable) entityPersister ).loadByUniqueKey( + entityInstance = entityPersister.loadByUniqueKey( uniqueKeyPropertyName, key, session