HHH-15893 - Clean-up NaturalIdMapping for API

HHH-15894 - Clean-up EntityMappingType for API
This commit is contained in:
Steve Ebersole 2022-12-19 10:35:16 -06:00
parent c21fef3a66
commit 1715f09a89
25 changed files with 398 additions and 292 deletions

View File

@ -130,7 +130,7 @@ class DatabaseSnapshotExecutor {
);
entityDescriptor.visitAttributeMappings(
entityDescriptor.forEachAttributeMapping(
attributeMapping -> {
final NavigablePath navigablePath = rootPath.append( attributeMapping.getAttributeName() );
domainResults.add(

View File

@ -44,7 +44,7 @@ public class SingleIdEntityLoaderProvidedQueryImpl<T> implements SingleIdEntityL
//noinspection unchecked
final QueryImplementor<T> query = namedQueryMemento.toQuery(
session,
entityDescriptor.getMappedJavaType().getJavaTypeClass()
(Class<T>) entityDescriptor.getMappedJavaType().getJavaTypeClass()
);
//noinspection unchecked

View File

@ -20,6 +20,9 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
* the associated entity
*/
public interface Discriminatable {
/**
* Apply the discriminator as a predicate via the {@code predicateConsumer}
*/
void applyDiscriminator(
Consumer<Predicate> predicateConsumer,
String alias,

View File

@ -14,7 +14,6 @@ import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.spi.SqlSelection;
@ -237,7 +236,7 @@ public interface EmbeddableMappingType extends ManagedMappingType, SelectableMap
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
visitAttributeMappings(
forEachAttributeMapping(
attributeMapping -> attributeMapping.applySqlSelections( navigablePath, tableGroup, creationState )
);
}
@ -248,7 +247,7 @@ public interface EmbeddableMappingType extends ManagedMappingType, SelectableMap
TableGroup tableGroup,
DomainResultCreationState creationState,
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
visitAttributeMappings(
forEachAttributeMapping(
attributeMapping ->
attributeMapping.applySqlSelections(
navigablePath,

View File

@ -11,74 +11,81 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.Filter;
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;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.mapping.Contributable;
import org.hibernate.metamodel.UnsupportedMappingException;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.AttributeMappingsMap;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.Entity;
import static org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.UNFETCHED_PROPERTY;
/**
* Mapping of an entity
*
* @see jakarta.persistence.Entity
* @see jakarta.persistence.metamodel.EntityType
*
* @author Steve Ebersole
*/
public interface EntityMappingType
extends ManagedMappingType, EntityValuedModelPart, Loadable, Restrictable, Discriminatable {
/**
* Safety-net.
* The entity name.
* <p/>
* For most entities, this will be the fully-qualified name
* of the entity class. The alternative is an explicit
* {@linkplain JaxbEntity#getName() entity-name} which takes precedence if provided
*
* todo (6.0) : do we really need to expose?
* @apiNote Different from {@link Entity#name()}, which is just a glorified
* SQM "import" name
*/
EntityPersister getEntityPersister();
default String getContributor() {
// todo (6.0) : needed for the HHH-14470 half related to HHH-14469
return "orm";
}
String getEntityName();
/**
* Describes how the entity is represented in the application's domain model.
*/
default EntityRepresentationStrategy getRepresentationStrategy() {
return getEntityPersister().getRepresentationStrategy();
}
String getEntityName();
/**
* Details for the table this persister maps.
* Details for the table this entity maps. Generally this is the
* same as {@link #getIdentifierTableDetails()}, though may be different
* for subtypes in {@linkplain jakarta.persistence.InheritanceType#JOINED joined}
* and{@linkplain jakarta.persistence.InheritanceType#TABLE_PER_CLASS union}
* inheritance hierarchies
*
* @see #getIdentifierTableDetails()
*/
@ -95,16 +102,6 @@ public interface EntityMappingType
return this;
}
@Override
default String getPartName() {
return getEntityName();
}
@Override
default String getRootPathName() {
return getEntityName();
}
@Override
default JavaType<?> getJavaType() {
return getMappedJavaType();
@ -115,6 +112,12 @@ public interface EntityMappingType
return this;
}
/**
* Visit each "query space" for the mapped entity.
*
* @apiNote "Query space" is simply the table expressions to
* which the entity is mapped; the name is historical.
*/
void visitQuerySpaces(Consumer<String> querySpaceConsumer);
@ -130,62 +133,43 @@ public interface EntityMappingType
return findSubPart( name, treatTargetType );
}
@Override
ModelPart findSubPart(String name, EntityMappingType targetType);
@Override
void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType targetType);
@Override
<T> DomainResult<T> createDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState);
@Override
void applySqlSelections(
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState);
@Override
void applySqlSelections(
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState,
BiConsumer<SqlSelection,JdbcMapping> selectionConsumer);
@Override
default int getJdbcTypeCount() {
return forEachJdbcType( (index, jdbcMapping) -> {} );
}
@Override
int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action);
@Override
Object disassemble(Object value, SharedSessionContractImplementor session);
@Override
int forEachDisassembledJdbcValue(
Object value,
int offset,
JdbcValuesConsumer valuesConsumer,
SharedSessionContractImplementor session);
@Override
default int forEachJdbcValue(
Object value,
int offset,
JdbcValuesConsumer consumer,
SharedSessionContractImplementor session) {
return forEachDisassembledJdbcValue( disassemble( value, session ), offset, consumer, session );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Inheritance
/**
* Whether this entity is defined as abstract using the Java {@code abstract} keyword
*/
default boolean isAbstract() {
return getEntityPersister().getEntityMetamodel().isAbstract();
}
/**
* Whether this entity mapping has any subtype mappings
*/
default boolean hasSubclasses() {
return getEntityPersister().getEntityMetamodel().hasSubclasses();
}
/**
* The mapping for the entity which is the supertype for this entity
* mapping.
*
* @return The supertype mapping, or {@code null} if there is no
* supertype
*
* @apiNote This need not be the direct superclass of the entity as it
* is driven by mapping.
*/
default EntityMappingType getSuperMappingType() {
return null;
}
/**
* Get the name of the entity that is the "super class" for this entity
*
@ -195,12 +179,47 @@ public interface EntityMappingType
return getSuperMappingType().getEntityName();
}
default int getSubclassId() {
return getEntityPersister().getEntityMetamodel().getSubclassId();
/**
* Retrieve mappings for all subtypes
*/
default Collection<EntityMappingType> getSubMappingTypes() {
final MappingMetamodelImplementor mappingMetamodel = getEntityPersister().getFactory().getMappingMetamodel();
final Set<String> subclassEntityNames = getSubclassEntityNames();
final List<EntityMappingType> mappingTypes = new ArrayList<>( subclassEntityNames.size() );
for ( String subclassEntityName : subclassEntityNames ) {
mappingTypes.add( mappingMetamodel.getEntityDescriptor( subclassEntityName ) );
}
return mappingTypes;
}
default boolean hasSubclasses() {
return getEntityPersister().getEntityMetamodel().hasSubclasses();
/**
* Whether the passed entity mapping is the same as or is a supertype of
* this entity mapping
*/
default boolean isTypeOrSuperType(EntityMappingType targetType) {
return targetType == this;
}
/**
* Whether the passed mapping is (1) an entity mapping and (2) the same as or
* a supertype of this entity mapping
*
* @see #isTypeOrSuperType(EntityMappingType)
*/
default boolean isTypeOrSuperType(ManagedMappingType targetType) {
if ( targetType instanceof EntityMappingType ) {
return isTypeOrSuperType( (EntityMappingType) targetType );
}
return false;
}
/**
* A value that uniquely identifies an entity mapping relative to its
* inheritance hierarchy
*/
default int getSubclassId() {
return getEntityPersister().getEntityMetamodel().getSubclassId();
}
default Set<String> getSubclassEntityNames() {
@ -212,111 +231,15 @@ public interface EntityMappingType
*/
boolean isExplicitPolymorphism();
/**
* The discriminator value which indicates this entity mapping
*/
Object getDiscriminatorValue();
default String getDiscriminatorSQLValue() {
return getDiscriminatorValue().toString();
}
String getSubclassForDiscriminatorValue(Object value);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute mappings
AttributeMapping findDeclaredAttributeMapping(String name);
/**
* Get the number of attributes defined on this class - do not access attributes defined on the super
*/
default int getNumberOfDeclaredAttributeMappings() {
return getDeclaredAttributeMappings().size();
}
/**
* Get access to the attributes defined on this class - do not access attributes defined on the super
*/
AttributeMappingsMap getDeclaredAttributeMappings();
/**
* Visit attributes defined on this class - do not visit attributes defined on the super
*/
void visitDeclaredAttributeMappings(Consumer<? super AttributeMapping> action);
default EntityMappingType getSuperMappingType() {
return null;
}
default Collection<EntityMappingType> getSubMappingTypes() {
final MappingMetamodelImplementor mappingMetamodel = getEntityPersister().getFactory().getMappingMetamodel();
final Set<String> subclassEntityNames = getSubclassEntityNames();
final List<EntityMappingType> mappingTypes = new ArrayList<>( subclassEntityNames.size() );
for ( String subclassEntityName : subclassEntityNames ) {
mappingTypes.add( mappingMetamodel.getEntityDescriptor( subclassEntityName ) );
}
return mappingTypes;
}
default boolean isTypeOrSuperType(EntityMappingType targetType) {
return targetType == this;
}
default boolean isTypeOrSuperType(ManagedMappingType targetType) {
if ( targetType instanceof EntityMappingType ) {
return isTypeOrSuperType( (EntityMappingType) targetType );
}
return false;
}
default SqmMultiTableMutationStrategy getSqmMultiTableMutationStrategy(){
return getEntityPersister().getSqmMultiTableMutationStrategy();
}
default SqmMultiTableInsertStrategy getSqmMultiTableInsertStrategy() {
return getEntityPersister().getSqmMultiTableInsertStrategy();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Special model parts - identifier, discriminator, etc
EntityIdentifierMapping getIdentifierMapping();
EntityDiscriminatorMapping getDiscriminatorMapping();
EntityVersionMapping getVersionMapping();
NaturalIdMapping getNaturalIdMapping();
EntityRowIdMapping getRowIdMapping();
/**
* Visit the mappings, but limited to just attributes defined
* in the targetType or its super-type(s) if any.
*
* @apiNote Passing {@code null} indicates that subclasses should be included. This
* matches legacy non-TREAT behavior and meets the need for EntityGraph processing
*/
default void visitAttributeMappings(Consumer<? super AttributeMapping> action, EntityMappingType targetType) {
getAttributeMappings().forEach( action );
}
/**
* Walk this type's attributes as well as its sub-type's
*/
default void visitSubTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
// by default do nothing
}
/**
* Walk this type's attributes as well as its super-type's
*/
default void visitSuperTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
// by default do nothing
}
void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer);
default EntityMappingType getRootEntityDescriptor() {
final EntityMappingType superMappingType = getSuperMappingType();
@ -354,20 +277,149 @@ public interface EntityMappingType
default void pruneForSubclasses(TableGroup tableGroup, Set<String> treatedEntityNames) {
}
default boolean isAbstract() {
return getEntityPersister().getEntityMetamodel().isAbstract();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Special model parts - identifier, discriminator, etc
/**
* Mapping details for the entity's identifier. This is shared across all
* entity mappings within an inheritance hierarchy.
*/
EntityIdentifierMapping getIdentifierMapping();
/**
* Mapping details for the entity's discriminator. This is shared across all
* entity mappings within an inheritance hierarchy.
*/
EntityDiscriminatorMapping getDiscriminatorMapping();
/**
* Mapping details for the entity's version when using the
* {@linkplain OptimisticLockStyle#VERSION version strategy}.
* This is shared across all entity mappings within an inheritance
* hierarchy.
*
* @return The version mapping, or null if the entity is (1) defined
* with a strategy other than {@link OptimisticLockStyle#VERSION} or
* (2) defined without optimistic locking
*
* @see #optimisticLockStyle
*/
EntityVersionMapping getVersionMapping();
/**
* The type of optimistic locking, if any, defined for this entity mapping
*/
default OptimisticLockStyle optimisticLockStyle() {
return OptimisticLockStyle.NONE;
}
/**
* The mapping for the natural-id of the entity, if one is defined
*/
NaturalIdMapping getNaturalIdMapping();
/**
* The mapping for the row-id of the entity, if one is defined.
*/
EntityRowIdMapping getRowIdMapping();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute mappings
/**
* The total number of attributes for this entity, including those
* declared on supertype mappings
*/
@Override
default int getNumberOfAttributeMappings() {
return getEntityPersister().getNumberOfAttributeMappings();
}
/**
* The attributes mapping for this entity, including those
* declared on supertype mappings
*/
@Override
default AttributeMappingsList getAttributeMappings() {
return getEntityPersister().getAttributeMappings();
}
/**
* Visit each {@linkplain #getAttributeMappings() attribute mapping}
*
* @see #getAttributeMappings()
*/
@Override
default void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
getAttributeMappings().forEach( action );
}
/**
* Retrieve an attribute mapping by position, relative to
* {@linkplain #getAttributeMappings() all attributes}
*/
@Override
default AttributeMapping getAttributeMapping(int position) {
return getEntityPersister().getAttributeMapping( position );
}
/**
* Find an attribute-mapping, declared on this entity mapping (not super or
* subs), by name
*/
AttributeMapping findDeclaredAttributeMapping(String name);
/**
* Get the number of attributes defined on this entity mapping - do not access
* attributes defined on the super
*/
default int getNumberOfDeclaredAttributeMappings() {
return getDeclaredAttributeMappings().size();
}
/**
* Get access to the attributes defined on this class - do not access attributes defined on the super
*/
AttributeMappingsMap getDeclaredAttributeMappings();
/**
* Visit attributes defined on this class - do not visit attributes defined on the super
*/
void visitDeclaredAttributeMappings(Consumer<? super AttributeMapping> action);
/**
* Visit the mappings, but limited to just attributes defined
* in the targetType or its super-type(s) if any.
*
* @apiNote Passing {@code null} indicates that subclasses should be included. This
* matches legacy non-TREAT behavior and meets the need for EntityGraph processing
*/
default void visitAttributeMappings(Consumer<? super AttributeMapping> action, EntityMappingType targetType) {
getAttributeMappings().forEach( action );
}
/**
* Walk this type's attributes as well as its sub-type's
*/
default void visitSubTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
// by default do nothing
}
/**
* Walk this type's attributes as well as its super-type's
*/
default void visitSuperTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
// by default do nothing
}
void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer);
interface ConstraintOrderedTableConsumer {
void consume(String tableExpression, Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier);
}
@Override
default void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
getAttributeMappings().forEach( action );
}
// Customer <- DomesticCustomer <- OtherCustomer
@Deprecated(forRemoval = true)
@ -377,9 +429,9 @@ public interface EntityMappingType
// todo (6.0) : getNumberOfAttributeMappings() needs to be fixed for this to work - bad walking of hierarchy
final Object[] values = new Object[ getNumberOfAttributeMappings() ];
visitAttributeMappings(
forEachAttributeMapping(
attribute -> {
final DomainResultAssembler assembler = assemblerMapping.get( attribute );
final DomainResultAssembler<?> assembler = assemblerMapping.get( attribute );
final Object value;
if ( assembler == null ) {
value = UNFETCHED_PROPERTY;
@ -430,6 +482,27 @@ public interface EntityMappingType
return getEntityPersister().isAffectedByEnabledFetchProfiles( influencers );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SQM handling
default SqmMultiTableMutationStrategy getSqmMultiTableMutationStrategy(){
return getEntityPersister().getSqmMultiTableMutationStrategy();
}
default SqmMultiTableInsertStrategy getSqmMultiTableInsertStrategy() {
return getEntityPersister().getSqmMultiTableInsertStrategy();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SQL AST generation
@Override
default String getSqlAliasStem() {
return getEntityPersister().getSqlAliasStem();
}
@Override
default TableGroup createRootTableGroup(
boolean canUseInnerJoins,
@ -495,30 +568,10 @@ public interface EntityMappingType
}
@Override
default int getNumberOfAttributeMappings() {
return getEntityPersister().getNumberOfAttributeMappings();
}
@Override
default AttributeMappingsList getAttributeMappings() {
return getEntityPersister().getAttributeMappings();
}
@Override
default AttributeMapping getAttributeMapping(int position) {
return getEntityPersister().getAttributeMapping( position );
}
@Override
default JavaType getMappedJavaType() {
default JavaType<?> getMappedJavaType() {
return getEntityPersister().getMappedJavaType();
}
@Override
default String getSqlAliasStem() {
return getEntityPersister().getSqlAliasStem();
}
@Override
default int getNumberOfFetchables() {
return getEntityPersister().getNumberOfFetchables();
@ -567,4 +620,30 @@ public interface EntityMappingType
SqlAstCreationState creationState) {
getEntityPersister().applyWhereRestrictions( predicateConsumer, tableGroup, useQualifier, creationState );
}
/**
* Safety-net.
*/
// todo (6.0) : look to remove need for this. at the very least, move it to an SPI contract
@Internal
EntityPersister getEntityPersister();
/**
* @deprecated See {@link Contributable#getContributor()}
*/
@Deprecated
default String getContributor() {
// todo (6.0) : needed for the HHH-14470 half related to HHH-14469
return "orm";
}
@Override
default String getPartName() {
return getEntityName();
}
@Override
default String getRootPathName() {
return getEntityName();
}
}

View File

@ -29,6 +29,9 @@ import org.hibernate.sql.results.graph.FetchableContainer;
* @author Steve Ebersole
*/
public interface EntityValuedModelPart extends FetchableContainer {
/**
* The descriptor of the entity that is the type for this part
*/
EntityMappingType getEntityMappingType();
default ModelPart findSubPart(String name) {

View File

@ -14,8 +14,9 @@ import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.type.descriptor.java.JavaType;
/**
* Commonality in regards to the mapping type system for all managed domain
* types - entity types, mapped-superclass types, composite types, etc
* Mapping-model corollary to JPA's {@link jakarta.persistence.metamodel.ManagedType}
*
* @see jakarta.persistence.metamodel.ManagedType
*
* @author Steve Ebersole
*/
@ -40,6 +41,11 @@ public interface ManagedMappingType extends MappingType, FetchableContainer {
*/
AttributeMapping getAttributeMapping(int position);
/**
* Find an attribute by name.
*
* @return The named attribute, or {@code null} if no match was found
*/
default AttributeMapping findAttributeMapping(String name) {
return null;
}
@ -52,7 +58,7 @@ public interface ManagedMappingType extends MappingType, FetchableContainer {
/**
* Visit attributes defined on this class and any supers
*/
void visitAttributeMappings(Consumer<? super AttributeMapping> action);
void forEachAttributeMapping(Consumer<? super AttributeMapping> action);
/**
* Visit attributes defined on this class and any supers
@ -61,14 +67,26 @@ public interface ManagedMappingType extends MappingType, FetchableContainer {
getAttributeMappings().indexedForEach( consumer );
}
/**
* Extract the individual attribute values from the entity instance
*/
Object[] getValues(Object instance);
/**
* Extract a specific attribute value from the entity instance, by position
*/
default Object getValue(Object instance, int position) {
return getAttributeMapping( position ).getValue( instance );
}
/**
* Inject the attribute values into the entity instance
*/
void setValues(Object instance, Object[] resolvedValues);
/**
* Inject a specific attribute value into the entity instance, by position
*/
default void setValue(Object instance, int position, Object value) {
getAttributeMapping( position ).setValue( instance, value );
}

View File

@ -9,10 +9,13 @@ package org.hibernate.metamodel.mapping;
import org.hibernate.type.descriptor.java.JavaType;
/**
* Parts of the ModelPart hierarchy that are type descriptors, as opposed to attributes e.g.
* Common descriptor for types in the mapping model - entities, embeddables, String, Integer, etc
*
* @author Steve Ebersole
*/
public interface MappingType {
/**
* The {@linkplain JavaType descriptor} descriptor for the mapped Java type
*/
JavaType<?> getMappedJavaType();
}

View File

@ -20,8 +20,9 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.type.descriptor.java.JavaType;
/**
* Describes a mapping related to any part of the app's domain model - e.g.
* an attribute, an entity identifier, collection elements, etc
* Base descriptor, within the mapping model, for any part of the
* application's domain model - an attribute,
* an entity identifier, collection elements, etc
*
* @see DomainResultProducer
* @see jakarta.persistence.metamodel.Bindable
@ -80,15 +81,9 @@ public interface ModelPart extends MappingModelExpressible {
* Whether this model part describes something that physically
* exists in the domain model.
* <p/>
* For example, take an entity defining its identifier with multiple
* {@link jakarta.persistence.Id} attributes; a "non-aggregated" identifier.
* Internally, Hibernate models the
* {@linkplain EntityMappingType#getIdentifierMapping() identifier mapping}
* for that entity as a virtual {@link EmbeddableMappingType}. The entity
* might also define an {@link jakarta.persistence.IdClass}, but that is a
* different mapping; in this case, the entity will have 2 mappings - one
* physical (the {@link jakarta.persistence.IdClass}) and the other virtual
* (the "non-aggregated" embeddable)
* For example, an entity's {@linkplain EntityDiscriminatorMapping discriminator}
* is part of the model, but is not a physical part of the domain model - there
* is no "discriminator attribute".
* <p/>
* Also indicates whether the part is castable to {@link VirtualModelPart}
*/

View File

@ -14,7 +14,28 @@ import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
import org.hibernate.loader.ast.spi.NaturalIdLoader;
/**
* Mapping for an entity's natural-id, if one is defined
* Mapping for an entity's natural-id, if one is defined.
* <p/>
* Natural identifiers are an alternative form of uniquely
* identifying a specific row. In this sense, they are similar
* to a primary key. In fact most natural identifiers will also
* be classified as "candidate keys" (as in a column or group of
* columns that are considered candidates for primary-key).
* <p/>
* However, a natural id has fewer restrictions than a primary
* key. While these lessened restrictions make them inappropriate
* for use as a primary key, they are still generally usable as
* unique locators with caveats. General reasons a natural id
* might be inappropriate for use as a primary key are<ul>
* <li>it contains nullable values</li>
* <li>it contains modifiable values</li>
* </ul>
* <p/>
* See other sources for a more complete discussion of data modeling.
*
* @see org.hibernate.Session#byNaturalId
* @see org.hibernate.Session#bySimpleNaturalId
* @see org.hibernate.Session#byMultipleNaturalId
*
* @author Steve Ebersole
*/

View File

@ -21,8 +21,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
*/
public interface Restrictable extends FilterRestrictable, WhereRestrictable {
/**
* Applies the base set of restrictions. The impact varies based on
* Restrictable type - some apply restrictions for filter, where and/or discriminator
* Applies the base set of restrictions.
*/
void applyBaseRestrictions(
Consumer<Predicate> predicateConsumer,

View File

@ -49,8 +49,8 @@ import org.hibernate.metamodel.mapping.SelectablePath;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.internal.MutableAttributeMappingList;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.spi.NavigablePath;
@ -655,7 +655,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
@Override
public void visitFetchables(Consumer<? super Fetchable> consumer, EntityMappingType treatTargetType) {
visitAttributeMappings( consumer );
forEachAttributeMapping( consumer );
}
@Override
@ -880,7 +880,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
}
@Override
public void visitAttributeMappings(final Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(final Consumer<? super AttributeMapping> action) {
attributeMappings.forEach( action );
}
@ -898,7 +898,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
visitAttributeMappings( consumer );
forEachAttributeMapping( consumer );
}
@Override

View File

@ -15,6 +15,7 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.Generator;
import org.hibernate.generator.InDatabaseGenerator;
import org.hibernate.loader.ast.internal.LoaderSelectBuilder;
import org.hibernate.loader.ast.internal.NoCallbackExecutionContext;
@ -30,7 +31,6 @@ import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.generator.Generator;
import static org.hibernate.sql.results.spi.ListResultsConsumer.UniqueSemantic.FILTER;
@ -91,7 +91,7 @@ public class GeneratedValuesProcessor {
// GenerationTiming.NEVER even if they have attributes that would need generation
final Generator[] generators = entityDescriptor.getEntityPersister().getEntityMetamodel().getGenerators();
final List<AttributeMapping> generatedValuesToSelect = new ArrayList<>();
entityDescriptor.visitAttributeMappings( mapping -> {
entityDescriptor.forEachAttributeMapping( mapping -> {
final Generator generator = generators[ mapping.getStateArrayPosition() ];
if ( generator != null
&& generator.generatedByDatabase()

View File

@ -36,8 +36,8 @@ import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.internal.MutableAttributeMappingList;
import org.hibernate.property.access.internal.PropertyAccessStrategyMapImpl;
import org.hibernate.property.access.spi.PropertyAccess;
@ -53,8 +53,6 @@ import org.hibernate.type.CompositeType;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.CompositeTypeImplementor;
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.getAttributeMetadata;
/**
* EmbeddableMappingType implementation describing an {@link jakarta.persistence.IdClass}
*/
@ -322,7 +320,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
forEachAttribute( (index, attribute) -> action.accept( attribute ) );
}

View File

@ -20,6 +20,7 @@ import org.hibernate.loader.ast.internal.SimpleNaturalIdLoader;
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
import org.hibernate.loader.ast.spi.NaturalIdLoader;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingType;
@ -57,6 +58,10 @@ public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping implements
}
public SingularAttributeMapping getAttribute() {
return attribute;
}
@Override
public void verifyFlushState(Object id, Object[] currentState, Object[] loadedState, SharedSessionContractImplementor session) {
if ( isMutable() ) {
@ -165,10 +170,6 @@ public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping implements
return getJavaType().coerce( normalizedValue, this );
}
public SingularAttributeMapping getAttribute() {
return attribute;
}
@Override
public List<SingularAttributeMapping> getNaturalIdAttributes() {
return Collections.singletonList( attribute );
@ -269,4 +270,9 @@ public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping implements
public TypeConfiguration getTypeConfiguration() {
return typeConfiguration;
}
@Override
public AttributeMapping asAttributeMapping() {
return getAttribute();
}
}

View File

@ -26,8 +26,8 @@ import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.internal.MutableAttributeMappingList;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
@ -241,7 +241,7 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
forEachAttribute( (index, attribute) -> action.accept( attribute ) );
}

View File

@ -871,7 +871,7 @@ public abstract class AbstractEntityPersister
}
public String getDiscriminatorColumnReaderTemplate() {
if ( getSubMappingTypes().size() == 1 ) {
if ( getSubclassEntityNames().size() == 1 ) {
return getDiscriminatorSQLValue();
}
else {
@ -4575,7 +4575,7 @@ public abstract class AbstractEntityPersister
// org.hibernate.metamodel.mapping.EntityMappingType
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
this.attributeMappings.forEach( action );
}
@ -5472,7 +5472,7 @@ public abstract class AbstractEntityPersister
ImmutableAttributeMappingList.Builder builder = new ImmutableAttributeMappingList.Builder( sizeHint );
if ( superMappingType != null ) {
superMappingType.visitAttributeMappings( builder::add );
superMappingType.forEachAttributeMapping( builder::add );
}
for ( AttributeMapping am : declaredAttributeMappings.valueIterator() ) {
@ -5766,7 +5766,7 @@ public abstract class AbstractEntityPersister
@Override
public void visitSubTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
visitAttributeMappings( action );
forEachAttributeMapping( action );
if ( subclassMappingTypes != null ) {
for ( EntityMappingType subType : subclassMappingTypes.values() ) {
subType.visitDeclaredAttributeMappings( action );

View File

@ -164,7 +164,7 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
throw new UnsupportedOperationException();
}

View File

@ -14,6 +14,7 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
@ -42,9 +43,9 @@ import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.AttributeMappingsMap;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstJoinType;
@ -173,8 +174,8 @@ public class AnonymousTupleEntityValuedModelPart
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
delegate.getEntityMappingType().visitAttributeMappings( action );
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
delegate.getEntityMappingType().forEachAttributeMapping( action );
}
@Override
@ -640,13 +641,13 @@ public class AnonymousTupleEntityValuedModelPart
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return delegate.getEntityMappingType().getSubclassForDiscriminatorValue( value );
public EntityVersionMapping getVersionMapping() {
return delegate.getEntityMappingType().getVersionMapping();
}
@Override
public EntityVersionMapping getVersionMapping() {
return delegate.getEntityMappingType().getVersionMapping();
public OptimisticLockStyle optimisticLockStyle() {
return delegate.getEntityMappingType().optimisticLockStyle();
}
@Override

View File

@ -15,7 +15,6 @@ import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.named.FetchMemento;
import org.hibernate.query.named.FetchMementoBasic;
import org.hibernate.query.named.ResultMementoEntity;
@ -25,6 +24,7 @@ import org.hibernate.query.results.ResultBuilderEntityValued;
import org.hibernate.query.results.complete.CompleteResultBuilderEntityJpa;
import org.hibernate.query.results.complete.DelayedFetchBuilderBasicPart;
import org.hibernate.query.results.implicit.ImplicitFetchBuilderBasic;
import org.hibernate.spi.NavigablePath;
/**
* @author Steve Ebersole
@ -85,7 +85,7 @@ public class ResultMementoEntityJpa implements ResultMementoEntity, FetchMemento
final boolean isEnhancedForLazyLoading = entityDescriptor.getRepresentationStrategy().isBytecodeEnhanced();
// Implicit basic fetches are DELAYED by default, so register fetch builders for the remaining basic fetchables
entityDescriptor.visitAttributeMappings(
entityDescriptor.forEachAttributeMapping(
attributeMapping -> {
final Function<String, FetchBuilder> fetchBuilderCreator;
if ( attributeMapping instanceof BasicValuedModelPart ) {

View File

@ -9,7 +9,6 @@ package org.hibernate.sql.ast.tree.from;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBase;
@ -19,12 +18,12 @@ import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.predicate.Predicate;
/**
* Contract for things that can produce the {@link TableGroup} that is the root of a
* from-clause
* Contract for things that can produce the {@link TableGroup} that is a root of a
* {@link FromClause#getRoots() from-clause}
*
* @author Steve Ebersole
*/
public interface RootTableGroupProducer extends TableGroupProducer, ModelPartContainer {
public interface RootTableGroupProducer extends TableGroupProducer {
/**
* Create a root TableGroup as defined by this producer
*/

View File

@ -6,8 +6,6 @@
*/
package org.hibernate.sql.results.graph.entity;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
@ -24,7 +22,6 @@ import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.basic.BasicFetch;
import org.hibernate.type.descriptor.java.JavaType;
@ -90,7 +87,7 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
TableGroup entityTableGroup) {
final MappingType mappingType = identifierMapping.getPartMappingType();
if ( mappingType instanceof ManagedMappingType ) {
( (ManagedMappingType) mappingType ).visitAttributeMappings(
( (ManagedMappingType) mappingType ).forEachAttributeMapping(
attributeMapping -> {
if ( attributeMapping instanceof ToOneAttributeMapping ) {
( (ToOneAttributeMapping) attributeMapping ).getForeignKeyDescriptor()

View File

@ -58,9 +58,9 @@ import org.hibernate.metamodel.mapping.TableDetails;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.AttributeMappingsMap;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.spi.PersisterClassResolver;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
@ -722,11 +722,6 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
return null;
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return null;
}
@Override
public NaturalIdMapping getNaturalIdMapping() {
return null;
@ -773,7 +768,7 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
}

View File

@ -55,9 +55,9 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.orm.test.jpa.SettingsGenerator;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.AttributeMappingsMap;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
import org.hibernate.persister.spi.PersisterClassResolver;
import org.hibernate.persister.spi.PersisterCreationContext;
@ -770,11 +770,6 @@ public class PersisterClassProviderTest {
return null;
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return null;
}
@Override
public NaturalIdMapping getNaturalIdMapping() {
return null;
@ -791,7 +786,7 @@ public class PersisterClassProviderTest {
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
}

View File

@ -54,9 +54,9 @@ import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.TableDetails;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.AttributeMappingsMap;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
@ -812,11 +812,6 @@ public class CustomPersister implements EntityPersister {
return null;
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return null;
}
@Override
public NaturalIdMapping getNaturalIdMapping() {
return null;
@ -863,7 +858,7 @@ public class CustomPersister implements EntityPersister {
}
@Override
public void visitAttributeMappings(Consumer<? super AttributeMapping> action) {
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
}