HHH-16407 - EntityPersister and CollectionPersister deprecations

This commit is contained in:
Steve Ebersole 2023-03-30 11:46:31 -05:00
parent 6b8efd01fa
commit 7db9bc83c1
25 changed files with 607 additions and 422 deletions

View File

@ -243,7 +243,8 @@ public class PersistentBag<E> extends AbstractPersistentCollection<E> implements
@Override
public void initializeEmptyCollection(CollectionPersister persister) {
assert bag == null;
bag = (List<E>) persister.getCollectionType().instantiate( 0 );
//noinspection unchecked
bag = (List<E>) persister.getCollectionSemantics().instantiateRaw( 0, persister );
endRead();
}

View File

@ -87,7 +87,8 @@ public class PersistentList<E> extends AbstractPersistentCollection<E> implement
@SuppressWarnings("unchecked")
public void initializeEmptyCollection(CollectionPersister persister) {
assert list == null;
list = (List<E>) persister.getCollectionType().instantiate( 0 );
//noinspection unchecked
list = (List<E>) persister.getCollectionSemantics().instantiateRaw( 0, persister );
endRead();
}
@ -121,7 +122,7 @@ public class PersistentList<E> extends AbstractPersistentCollection<E> implement
final int size = array.length;
assert list == null;
this.list = (List<E>) persister.getCollectionType().instantiate( size );
list = (List<E>) persister.getCollectionSemantics().instantiateRaw( size, persister );
for ( Serializable arrayElement : array ) {
list.add( (E) persister.getElementType().assemble( arrayElement, getSession(), owner ) );

View File

@ -94,7 +94,8 @@ public class PersistentMap<K,E> extends AbstractPersistentCollection<E> implemen
@Override
public void initializeEmptyCollection(CollectionPersister persister) {
assert map == null;
map = (Map<K,E>) persister.getCollectionType().instantiate( 0 );
//noinspection unchecked
map = (Map<K,E>) persister.getCollectionSemantics().instantiateRaw( 0, persister );
endRead();
}

View File

@ -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<E> extends AbstractPersistentCollection<E> implements
@Override
public void initializeEmptyCollection(CollectionPersister persister) {
assert set == null;
set = (Set<E>) persister.getCollectionType().instantiate( 0 );
//noinspection unchecked
set = (Set<E>) persister.getCollectionSemantics().instantiateRaw( 0, persister );
endRead();
}

View File

@ -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,21 +261,77 @@ 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()
final MappingMetamodelImpl mappingMetamodelImpl = new MappingMetamodelImpl( typeConfiguration, serviceRegistry );
runtimeMetamodelsImpl.setMappingMetamodel( mappingMetamodelImpl );
// because this calls back to the RuntimeMetamodelsImplementor
mappingMetamodelImpl.finishInitialization( this );
// need to set this after calling finishInitialization()
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
fetchProfiles = getFetchProfiles( bootMetamodel, runtimeMetamodels.getMappingMetamodel() );
defaultSessionOpenOptions = createDefaultSessionOpenOptionsIfPossible();
temporarySessionOpenOptions = defaultSessionOpenOptions == null ? null : buildTemporarySessionOpenOptions();
defaultStatelessOptions = defaultSessionOpenOptions == null ? null : withStatelessOptions();
fastSessionServices = new FastSessionServices( this );
wrapperOptions = new SessionFactoryBasedWrapperOptions( this );
currentSessionContext = buildCurrentSessionContext();
// re-scope the TypeConfiguration to this SessionFactory,
// now that we are (almost) fully-initialized ... note,
// we could have done this earlier, but then it's hard to
// really know or control who's calling back to us while
// we're in an incompletely-initialized state
typeConfiguration.scope( this );
observer.sessionFactoryCreated( this );
// As last operation, delete all caches from ReflectionManager
// (not modelled as a listener as we want this to be last)
bootstrapContext.getReflectionManager().reset();
}
catch ( Exception e ) {
disintegrate( e, integratorObserver );
try {
close();
}
catch (Exception closeException) {
LOG.debugf( "Eating error closing the SessionFactory after a failed attempt to start it" );
}
throw e;
}
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;
@ -295,7 +350,7 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
@Override
public MappingMetamodelImplementor getDomainModel() {
return mappingMetamodelImpl;
return mappingMetamodel;
}
@Override
@ -343,46 +398,6 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
return serviceRegistry;
}
};
// this needs to happen after the mapping metamodel is
// completely built, since we need to use the persisters
fetchProfiles = getFetchProfiles( bootMetamodel, runtimeMetamodels.getMappingMetamodel() );
defaultSessionOpenOptions = createDefaultSessionOpenOptionsIfPossible();
temporarySessionOpenOptions = defaultSessionOpenOptions == null ? null : buildTemporarySessionOpenOptions();
defaultStatelessOptions = defaultSessionOpenOptions == null ? null : withStatelessOptions();
fastSessionServices = new FastSessionServices( this );
wrapperOptions = new SessionFactoryBasedWrapperOptions( this );
currentSessionContext = buildCurrentSessionContext();
// re-scope the TypeConfiguration to this SessionFactory,
// now that we are (almost) fully-initialized ... note,
// we could have done this earlier, but then it's hard to
// really know or control who's calling back to us while
// we're in an incompletely-initialized state
typeConfiguration.scope( this );
observer.sessionFactoryCreated( this );
// As last operation, delete all caches from ReflectionManager
// (not modelled as a listener as we want this to be last)
bootstrapContext.getReflectionManager().reset();
}
catch ( Exception e ) {
disintegrate( e, integratorObserver );
try {
close();
}
catch (Exception closeException) {
LOG.debugf( "Eating error closing the SessionFactory after a failed attempt to start it" );
}
throw e;
}
LOG.debug( "Instantiated SessionFactory" );
}
private static Map<String, Generator> createGenerators(

View File

@ -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;
}
}

View File

@ -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:<ul>
* <li>{@link org.hibernate.metamodel.CollectionClassification} instance</li>
@ -174,9 +185,4 @@ public enum CollectionClassification {
return null;
}
public boolean isRowUpdatePossible() {
// anything other than BAG and SET
return this != BAG && this != SET;
}
}

View File

@ -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

View File

@ -174,6 +174,7 @@ public class PluralAttributeMappingImpl
else {
baseIndex = -1;
}
indexMetadata = new IndexMetadata() {
@Override
public CollectionPart getIndexDescriptor() {

View File

@ -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.
* <p/>
* 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
*/

View File

@ -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<String,String[]> 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<String,String[]> 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 {

View File

@ -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() );
}

View File

@ -80,15 +80,24 @@ import org.hibernate.type.Type;
* </li>
* </ol>
*
* @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();
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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<String> affectingFetchProfileNames;
private Map<String, SingleIdArrayLoadPlan> lazyLoadPlanByFetchGroup;
private final LockModeEnumMap<LockingStrategy> 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<String, SingleIdArrayLoadPlan> 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<String> 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<String,String[]> subclassPropertyAliases = new HashMap<>();
private final Map<String,String[]> 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<Property> 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<String,String[]> 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<Property> 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;
}
}

View File

@ -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 {
}

View File

@ -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)
*/

View File

@ -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<String, Integer> 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;
}
}

View File

@ -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

View File

@ -16,5 +16,12 @@
* defines a mechanism for persisting instances of a given
* collection role.
* </ul>
*
* @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 <b>is</b> intended for application use (things
* like {@link org.hibernate.SessionFactory}, {@link org.hibernate.Session},
* {@link org.hibernate.Transaction}, etc.).
*/
package org.hibernate.persister;

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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