HHH-15795 - Create ValuedModelPart interface

This commit is contained in:
Steve Ebersole 2022-12-02 15:44:50 -06:00
parent a4debae33a
commit f4a7be6b92
36 changed files with 400 additions and 185 deletions

View File

@ -20,7 +20,7 @@ import org.hibernate.type.descriptor.java.MutabilityPlanExposer;
* @author Steve Ebersole
*/
public interface AttributeMapping
extends ModelPart, ValueMapping, Fetchable, DatabaseSnapshotContributor, PropertyBasedMapping, MutabilityPlanExposer {
extends ValuedModelPart, Fetchable, DatabaseSnapshotContributor, PropertyBasedMapping, MutabilityPlanExposer {
/**
* The name of the mapped attribute
*/

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.metamodel.mapping;
import java.util.List;
import org.hibernate.sql.results.graph.Fetchable;
/**
@ -16,10 +18,37 @@ import org.hibernate.sql.results.graph.Fetchable;
*
* @author Steve Ebersole
*/
public interface BasicValuedModelPart extends BasicValuedMapping, ModelPart, Fetchable, SelectableMapping {
public interface BasicValuedModelPart extends BasicValuedMapping, ValuedModelPart, Fetchable, SelectableMapping {
@Override
default MappingType getPartMappingType() {
return this::getJavaType;
}
@Override
default int getJdbcTypeCount() {
return 1;
}
@Override
default List<JdbcMapping> getJdbcMappings() {
return BasicValuedMapping.super.getJdbcMappings();
}
@Override
default SelectableMapping getSelectable(int columnIndex) {
return this;
}
@Override
default int forEachSelectable(int offset, SelectableConsumer consumer) {
consumer.accept( offset, this );
return getJdbcTypeCount();
}
@Override
default int forEachSelectable(SelectableConsumer consumer) {
consumer.accept( 0, this );
return getJdbcTypeCount();
}
}

View File

@ -26,6 +26,7 @@ public interface Bindable extends JdbcMappingContainer {
/**
* The number of JDBC mappings
*/
@Override
default int getJdbcTypeCount() {
return forEachJdbcType( (index, jdbcMapping) -> {} );
}
@ -33,6 +34,7 @@ public interface Bindable extends JdbcMappingContainer {
/**
* The list of JDBC mappings
*/
@Override
default List<JdbcMapping> getJdbcMappings() {
final List<JdbcMapping> results = new ArrayList<>();
forEachJdbcType( (index, jdbcMapping) -> results.add( jdbcMapping ) );
@ -44,6 +46,7 @@ public interface Bindable extends JdbcMappingContainer {
*
* @apiNote Same as {@link #forEachJdbcType(int, IndexedConsumer)} starting from `0`
*/
@Override
default int forEachJdbcType(IndexedConsumer<JdbcMapping> action) {
return forEachJdbcType( 0, action );
}

View File

@ -19,7 +19,7 @@ import org.hibernate.type.descriptor.java.JavaTypedExpressible;
*
* @author Steve Ebersole
*/
public interface CollectionPart extends ModelPart, Fetchable, JavaTypedExpressible {
public interface CollectionPart extends ValuedModelPart, Fetchable, JavaTypedExpressible {
enum Nature {
/**
* The Collection element or Map element

View File

@ -24,6 +24,9 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
/**
* Describes an embeddable - the actual type
*
* @implNote Even though this represents the embeddable class, one is created for
* each embedded usage. This is done to help
*
* @see EmbeddableValuedModelPart
*/
public interface EmbeddableMappingType extends ManagedMappingType, SelectableMappings {

View File

@ -7,6 +7,7 @@
package org.hibernate.metamodel.mapping;
import java.util.List;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer;
@ -27,9 +28,29 @@ import org.hibernate.sql.results.graph.FetchableContainer;
* @see jakarta.persistence.EmbeddedId
* @see jakarta.persistence.Embeddable
*/
public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, FetchableContainer, TableGroupJoinProducer {
public interface EmbeddableValuedModelPart extends ValuedModelPart, Fetchable, FetchableContainer, TableGroupJoinProducer {
EmbeddableMappingType getEmbeddableTypeDescriptor();
@Override
default EmbeddableMappingType getMappedType() {
return getEmbeddableTypeDescriptor();
}
@Override
default ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
return getEmbeddableTypeDescriptor().findSubPart( name, treatTargetType );
}
@Override
default void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
getEmbeddableTypeDescriptor().forEachSubPart( consumer, treatTarget );
}
@Override
default void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
getEmbeddableTypeDescriptor().visitSubParts( consumer, treatTargetType );
}
@Override
default int getJdbcTypeCount() {
return getEmbeddableTypeDescriptor().getJdbcTypeCount();
@ -55,6 +76,11 @@ public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, Fetchab
return getEmbeddableTypeDescriptor().forEachJdbcValue( value, clause, offset, valuesConsumer, session );
}
@Override
default SelectableMapping getSelectable(int columnIndex) {
return getEmbeddableTypeDescriptor().getSelectable( columnIndex );
}
@Override
default int forEachSelectable(int offset, SelectableConsumer consumer) {
return getEmbeddableTypeDescriptor().forEachSelectable( offset, consumer );
@ -81,14 +107,6 @@ public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, Fetchab
return getEmbeddableTypeDescriptor().disassemble( value, session );
}
/**
* The main table expression (table name or subselect) that usually contains
* most of the columns to which this embedded is mapped.
*
* @apiNote Hibernate has historically required a composite to be mapped to the same table.
*/
String getContainingTableExpression();
/**
* @see org.hibernate.annotations.Parent
*/

View File

@ -18,7 +18,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
* @see jakarta.persistence.Id
* @see jakarta.persistence.EmbeddedId
*/
public interface EntityIdentifierMapping extends ValueMapping, ModelPart {
public interface EntityIdentifierMapping extends ValuedModelPart {
String ROLE_LOCAL_NAME = "{id}";

View File

@ -112,6 +112,10 @@ public interface EntityMappingType
return findSubPart( name, null );
}
default ModelPart findSubTypesSubPart(String name, EntityMappingType treatTargetType) {
return findSubPart( name, treatTargetType );
}
@Override
ModelPart findSubPart(String name, EntityMappingType targetType);

View File

@ -36,6 +36,11 @@ public interface EntityValuedModelPart extends FetchableContainer {
return getEntityMappingType().findSubPart( name, null );
}
@Override
default void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
getEntityMappingType().forEachSubPart( consumer, treatTarget );
}
@Override
default ModelPart findSubPart(String name, EntityMappingType targetType) {
return getEntityMappingType().findSubPart( name, targetType );

View File

@ -24,44 +24,24 @@ import org.hibernate.sql.results.graph.FetchParent;
/**
* Descriptor for foreign-keys
*/
public interface ForeignKeyDescriptor extends VirtualModelPart, ValueMapping {
enum Nature {
KEY,
TARGET;
public Nature inverse() {
return this == KEY ? TARGET : KEY;
}
}
interface Side {
Nature getNature();
ModelPart getModelPart();
}
public interface ForeignKeyDescriptor extends VirtualModelPart, ValuedModelPart {
String PART_NAME = "{fk}";
String TARGET_PART_NAME = "{fk-target}";
@Override
default String getPartName() {
return PART_NAME;
}
String getKeyTable();
String getTargetTable();
default String getTable(Nature nature) {
if ( nature == Nature.KEY ) {
return getKeyTable();
}
else {
return getTargetTable();
}
}
ModelPart getKeyPart();
ValuedModelPart getKeyPart();
ModelPart getTargetPart();
ValuedModelPart getTargetPart();
default ModelPart getPart(Nature nature) {
if ( nature == Nature.KEY ) {
@ -85,6 +65,11 @@ public interface ForeignKeyDescriptor extends VirtualModelPart, ValueMapping {
}
}
@Override
default String getContainingTableExpression() {
return getKeyTable();
}
/**
* Compare the 2 values
*/
@ -127,9 +112,7 @@ public interface ForeignKeyDescriptor extends VirtualModelPart, ValueMapping {
boolean isSimpleJoinPredicate(Predicate predicate);
@Override
default String getPartName() {
return PART_NAME;
}
SelectableMapping getSelectable(int columnIndex);
/**
* Visits the FK "referring" columns
@ -175,4 +158,19 @@ public interface ForeignKeyDescriptor extends VirtualModelPart, ValueMapping {
AssociationKey getAssociationKey();
boolean hasConstraint();
enum Nature {
KEY,
TARGET;
public Nature inverse() {
return this == KEY ? TARGET : KEY;
}
}
interface Side {
Nature getNature();
ValuedModelPart getModelPart();
}
}

View File

@ -6,10 +6,37 @@
*/
package org.hibernate.metamodel.mapping;
import java.util.function.Consumer;
import org.hibernate.mapping.IndexedConsumer;
/**
* Access to a group of ModelPart by name or for iteration
* Access to a group of ModelPart by name or for iteration.
*
* @author Steve Ebersole
*/
public interface ModelPartContainer extends Queryable {
public interface ModelPartContainer extends ModelPart {
ModelPart findSubPart(String name, EntityMappingType treatTargetType);
default void forEachSubPart(IndexedConsumer<ModelPart> consumer) {
forEachSubPart( consumer, null );
}
void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget);
void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType);
default ModelPart findByPath(String path) {
int nextStart = 0;
int dotIndex;
ModelPartContainer modelPartContainer = this;
while ( ( dotIndex = path.indexOf( '.', nextStart ) ) != -1 ) {
modelPartContainer = (ModelPartContainer) modelPartContainer.findSubPart(
path.substring( nextStart, dotIndex ),
null
);
nextStart = dotIndex + 1;
}
return modelPartContainer.findSubPart( path.substring( nextStart ), null );
}
}

View File

@ -1,82 +0,0 @@
/*
* 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.metamodel.mapping;
import java.util.function.Consumer;
import org.hibernate.spi.DotIdentifierSequence;
import org.hibernate.boot.spi.SessionFactoryOptions;
/**
* Defines a mapping model contract for things that can be queried in the HQL,
* Criteria, etc sense. Generally this
*
* @author Steve Ebersole
*/
public interface Queryable extends ModelPart {
/**
* For an entity, this form allows for Hibernate's "implicit treat" support -
* meaning it should find a sub-part whether defined on the entity, its
* super-type or even one of its sub-types.
*
* @implNote Logically the implementation should consider
* {@link org.hibernate.jpa.spi.JpaCompliance}. Not passed in because it
* is expected that implementors have access to the SessionFactory to access
* the JpaCompliance. See {@link SessionFactoryOptions#getJpaCompliance}
*/
ModelPart findSubPart(String name, EntityMappingType treatTargetType);
default ModelPart findByPath(String path) {
int nextStart = 0;
int dotIndex;
Queryable modelPartContainer = this;
while ( ( dotIndex = path.indexOf( '.', nextStart ) ) != -1 ) {
modelPartContainer = (Queryable) modelPartContainer.findSubPart(
path.substring( nextStart, dotIndex ),
null
);
nextStart = dotIndex + 1;
}
return modelPartContainer.findSubPart( path.substring( nextStart ), null );
}
default ModelPart resolveSubPart(DotIdentifierSequence path) {
return path.resolve(
(ModelPart) this,
(part, name) -> {
final String fullPath = part.getNavigableRole().getFullPath();
if ( fullPath.equals( name ) ) {
return part;
}
else {
return ( (Queryable) part ).findSubPart( name.substring( fullPath.length() + 1 ), null );
}
},
(part, name) -> ( (Queryable) part ).findSubPart( name, null )
);
}
/**
* For an entity, this form allows for Hibernate's "implicit treat" support -
* meaning it should find a sub-part whether defined on the entity or one of its sub-types.
*
* @implNote Logically the implementation should consider
* {@link org.hibernate.jpa.spi.JpaCompliance}. Not passed in because it
* is expected that implementors have access to the SessionFactory to access
* the JpaCompliance. See {@link SessionFactoryOptions#getJpaCompliance}
*/
default ModelPart findSubTypesSubPart(String name, EntityMappingType treatTargetType) {
return findSubPart( name, treatTargetType );
}
/**
* Like {@link #findSubPart}, this form visits all parts defined on the
* entity, its super-types and its sub-types.
*/
void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType);
}

View File

@ -0,0 +1,44 @@
/*
* 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.metamodel.mapping;
import java.util.List;
/**
* Describes a ModelPart that is also a ValueMapping (and therefore also a SelectableMappings).
* <p/>
* {@linkplain BasicValuedModelPart Basic} and {@linkplain EmbeddableValuedModelPart embedded}
* model-parts fall into this category.
*
* @author Steve Ebersole
*/
public interface ValuedModelPart extends ModelPart, ValueMapping, SelectableMappings {
/**
* The table which contains the columns mapped by this value
*/
String getContainingTableExpression();
@Override
default int getJdbcTypeCount() {
return ModelPart.super.getJdbcTypeCount();
}
@Override
default List<JdbcMapping> getJdbcMappings() {
return ModelPart.super.getJdbcMappings();
}
@Override
default int forEachSelectable(int offset, SelectableConsumer consumer) {
return ModelPart.super.forEachSelectable( offset, consumer );
}
@Override
default int forEachSelectable(SelectableConsumer consumer) {
return ModelPart.super.forEachSelectable( consumer );
}
}

View File

@ -90,6 +90,11 @@ public abstract class AbstractEntityCollectionPart implements EntityCollectionPa
return collectionDescriptor;
}
@Override
public EntityMappingType getMappedType() {
return getAssociatedEntityMappingType();
}
protected Set<String> getTargetKeyPropertyNames() {
return targetKeyPropertyNames;
}

View File

@ -438,6 +438,13 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
return null;
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
for ( int i = 0; i < attributes.size(); i++ ) {
consumer.accept( i, attributes.get(i) );
}
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
attributes.forEach( consumer );

View File

@ -29,6 +29,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.spi.NavigablePath;
@ -195,11 +196,24 @@ public class DiscriminatedAssociationAttributeMapping
throw new IndexOutOfBoundsException(position);
}
@Override
public String getContainingTableExpression() {
return getDiscriminatorPart().getContainingTableExpression();
}
@Override
public int getJdbcTypeCount() {
return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount();
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
if ( columnIndex == 0 ) {
return getDiscriminatorPart();
}
return getKeyPart();
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
if ( value == null ) {
@ -320,8 +334,8 @@ public class DiscriminatedAssociationAttributeMapping
@Override
public void visitFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
fetchableConsumer.accept( 0, getDiscriminatorPart() );
fetchableConsumer.accept( 1, getKeyPart() );
//noinspection unchecked,rawtypes
forEachSubPart( (IndexedConsumer) fetchableConsumer, treatTargetType );
}
@Override
@ -329,6 +343,12 @@ public class DiscriminatedAssociationAttributeMapping
return discriminatorMapping.findSubPart( name, treatTargetType );
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
consumer.accept( 0, getDiscriminatorPart() );
consumer.accept( 1, getKeyPart() );
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
consumer.accept( getDiscriminatorPart() );

View File

@ -22,6 +22,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.spi.NavigablePath;
@ -186,6 +187,11 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
return discriminatorMapping.getJavaType();
}
@Override
public MappingType getMappedType() {
return getPartMappingType();
}
@Override
public JavaType<?> getExpressibleJavaType() {
return getJavaType();
@ -206,6 +212,12 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
return discriminatorMapping.findSubPart( name, treatTargetType );
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
consumer.accept( 0, getDiscriminatorPart() );
consumer.accept( 1, getKeyPart() );
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
consumer.accept( getDiscriminatorPart() );
@ -228,11 +240,21 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
throw new IndexOutOfBoundsException(position);
}
@Override
public String getContainingTableExpression() {
return getDiscriminatorPart().getContainingTableExpression();
}
@Override
public int getJdbcTypeCount() {
return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount();
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
return getDiscriminatorPart().getSelectable( columnIndex );
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
return discriminatorMapping.getDiscriminatorPart().disassemble( value, session );

View File

@ -78,7 +78,6 @@ import org.hibernate.type.spi.TypeConfiguration;
* composite fks
*/
public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping implements SelectableMappings {
public static EmbeddableMappingTypeImpl from(
Component bootDescriptor,
CompositeType compositeType,
@ -786,6 +785,13 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
return findAttributeMapping( name );
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
consumer.accept( i, attributeMappings.get(i) );
}
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
visitAttributeMappings( consumer );

View File

@ -138,9 +138,9 @@ public class EmbeddedAttributeMapping
null,
inverseModelPart.getMappedFetchOptions(),
keyDeclaringType,
inverseModelPart instanceof PropertyBasedMapping ?
( (PropertyBasedMapping) inverseModelPart ).getPropertyAccess() :
null
inverseModelPart instanceof PropertyBasedMapping
? ( (PropertyBasedMapping) inverseModelPart ).getPropertyAccess()
: null
);
this.navigableRole = inverseModelPart.getNavigableRole().getParent().append( inverseModelPart.getFetchableName() );

View File

@ -487,6 +487,11 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
return true;
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
return keySelectableMappings.getSelectable( columnIndex );
}
@Override
public int visitKeySelectables(int offset, SelectableConsumer consumer) {
return keySelectableMappings.forEachSelectable( offset, consumer );

View File

@ -26,6 +26,7 @@ import org.hibernate.type.descriptor.java.JavaType;
* @author Steve Ebersole
*/
public interface EntityCollectionPart extends CollectionPart, EntityValuedFetchable {
enum Cardinality { ONE_TO_MANY, MANY_TO_MANY }
Cardinality getCardinality();
@ -59,6 +60,11 @@ public interface EntityCollectionPart extends CollectionPart, EntityValuedFetcha
return getJavaType();
}
@Override
default int getJdbcTypeCount() {
return CollectionPart.super.getJdbcTypeCount();
}
/**
* Perform any delayed initialization.
* <p>

View File

@ -363,6 +363,13 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
return null;
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
consumer.accept( i, attributeMappings.get( i ) );
}
}
@Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
attributeMappings.forEach( (attribute) -> {

View File

@ -35,6 +35,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.mapping.ValuedModelPart;
import org.hibernate.metamodel.mapping.VirtualModelPart;
import org.hibernate.persister.collection.BasicCollectionPersister;
import org.hibernate.persister.collection.CollectionPersister;
@ -78,7 +79,7 @@ import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelpe
*/
public class ManyToManyCollectionPart extends AbstractEntityCollectionPart implements EntityAssociationMapping {
private ForeignKeyDescriptor foreignKey;
private ModelPart fkTargetModelPart;
private ValuedModelPart fkTargetModelPart;
public ManyToManyCollectionPart(
Nature nature,
@ -140,6 +141,16 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
fkTargetModelPart.breakDownJdbcValues( domainValue, valueConsumer, session );
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
return fkTargetModelPart.getSelectable( columnIndex );
}
@Override
public String getContainingTableExpression() {
return fkTargetModelPart.getContainingTableExpression();
}
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
foreignKey.getKeyPart().forEachSelectable( offset, consumer );
@ -512,7 +523,7 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
}
}
private static ModelPart resolveNamedTargetPart(
private static ValuedModelPart resolveNamedTargetPart(
String targetPartName,
EntityMappingType entityMappingType,
CollectionPersister collectionDescriptor) {
@ -533,7 +544,7 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple
)
);
}
return namedPart;
return (ValuedModelPart) namedPart;
}
private ForeignKeyDescriptor createForeignKeyDescriptor(

View File

@ -18,6 +18,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstJoinType;
@ -102,10 +103,19 @@ public class OneToManyCollectionPart extends AbstractEntityCollectionPart implem
return getAssociatedEntityMappingType().getIdentifierMapping().getIdentifier( value );
}
@Override
public String getContainingTableExpression() {
return getCollectionDescriptor().getAttributeMapping().getKeyDescriptor().getContainingTableExpression();
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
return getCollectionDescriptor().getAttributeMapping().getKeyDescriptor().getSelectable( columnIndex );
}
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
return getCollectionDescriptor().getAttributeMapping().getKeyDescriptor().getKeyPart().forEachSelectable( offset, consumer );
// return super.forEachSelectable( offset, consumer );
}
@Override

View File

@ -31,8 +31,9 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.Queryable;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.metamodel.mapping.ordering.OrderByFragmentTranslator;
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
@ -844,8 +845,8 @@ public class PluralAttributeMappingImpl
@Override
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
if ( elementDescriptor instanceof Queryable ) {
final ModelPart subPart = ( (Queryable) elementDescriptor ).findSubPart( name, null );
if ( elementDescriptor instanceof ModelPartContainer ) {
final ModelPart subPart = ( (ModelPartContainer) elementDescriptor ).findSubPart( name, null );
if ( subPart != null ) {
return subPart;
}
@ -865,6 +866,20 @@ public class PluralAttributeMappingImpl
return null;
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
consumer.accept( 0, elementDescriptor );
int position = 1;
if ( indexDescriptor != null ) {
consumer.accept( position++, indexDescriptor );
}
if ( identifierDescriptor != null ) {
consumer.accept( position+1, identifierDescriptor );
}
}
@Override
public void applySqlSelections(
NavigablePath navigablePath, TableGroup tableGroup, DomainResultCreationState creationState) {
@ -893,22 +908,24 @@ public class PluralAttributeMappingImpl
}
}
@Override
public String getContainingTableExpression() {
return getKeyDescriptor().getKeyTable();
}
@Override
public int getJdbcTypeCount() {
int span = elementDescriptor.getJdbcTypeCount();
if ( indexDescriptor != null ) {
span += indexDescriptor.getJdbcTypeCount();
}
return span;
return 0;
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
return null;
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
int span = elementDescriptor.forEachJdbcType( offset, action );
if ( indexDescriptor != null ) {
span += indexDescriptor.forEachJdbcType( offset + span, action );
}
return span;
return 0;
}
@Override

View File

@ -402,6 +402,12 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
return targetSide.getModelPart().getMappedType();
}
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
consumer.accept( offset, this );
return 1;
}
@Override
public JavaType<?> getJavaType() {
return targetSide.getModelPart().getJdbcMapping().getJavaTypeDescriptor();
@ -518,6 +524,11 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
return keySide.getModelPart().getSelectionExpression();
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
return keySide.getModelPart();
}
@Override
public boolean isFormula() {
return keySide.getModelPart().isFormula();

View File

@ -48,6 +48,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.VirtualModelPart;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.collection.QueryableCollection;
@ -275,9 +276,11 @@ public class ToOneAttributeMapping
else {
final String targetTableName = MappingModelCreationHelper.getTableIdentifierExpression( manyToOne.getTable(), declaringEntityPersister.getFactory() );
if ( CollectionPart.Nature.fromNameExact( navigableRole.getParent().getLocalName() ) != null ) {
final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) declaringEntityPersister.resolveSubPart(
navigableRole.getParent().getParent()
);
// * the to-one's parent is directly a collection element or index
// * therefore, its parent-parent should be the collection itself
final String pluralAttributeName = StringHelper.unqualify( navigableRole.getParent().getParent().getLocalName() );
final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) declaringEntityPersister.findAttributeMapping( pluralAttributeName );
assert pluralAttribute != null;
final QueryableCollection persister = (QueryableCollection) pluralAttribute.getCollectionDescriptor();
isKeyTableNullable = !persister.getTableName().equals( targetTableName );
}
@ -2008,11 +2011,29 @@ public class ToOneAttributeMapping
}
}
@Override
public String getContainingTableExpression() {
if ( sideNature == ForeignKeyDescriptor.Nature.KEY ) {
return foreignKeyDescriptor.getKeyTable();
}
else {
return foreignKeyDescriptor.getTargetTable();
}
}
@Override
public int getJdbcTypeCount() {
return foreignKeyDescriptor.getJdbcTypeCount();
}
@Override
public SelectableMapping getSelectable(int columnIndex) {
if ( sideNature == ForeignKeyDescriptor.Nature.KEY ) {
return foreignKeyDescriptor.getSelectable( columnIndex );
}
return null;
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
return foreignKeyDescriptor.forEachJdbcType( offset, action );

View File

@ -283,6 +283,13 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
return null;
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
consumer.accept( i, attributeMappings.get( i ) );
}
}
@Override
public <T> DomainResult<T> createDomainResult(NavigablePath navigablePath, TableGroup tableGroup, String resultVariable, DomainResultCreationState creationState) {
throw new NotYetImplementedFor6Exception( getClass() );

View File

@ -98,11 +98,11 @@ import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.id.insert.UniqueKeySelectingDelegate;
import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.id.insert.BasicSelectingDelegate;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.id.insert.InsertReturningDelegate;
import org.hibernate.id.insert.UniqueKeySelectingDelegate;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.FilterAliasGenerator;
@ -167,7 +167,6 @@ import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.Queryable;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
@ -258,9 +257,9 @@ import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.Generator;
import org.hibernate.tuple.InDatabaseGenerator;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.entity.EntityBasedAssociationAttribute;
import org.hibernate.tuple.entity.EntityMetamodel;
@ -288,7 +287,7 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
* @author Gavin King
*/
public abstract class AbstractEntityPersister
implements OuterJoinLoadable, Queryable, ClassMetadata, UniqueKeyLoadable,
implements OuterJoinLoadable, ClassMetadata, UniqueKeyLoadable,
SQLLoadable, LazyPropertyInitializer, PostInsertIdentityPersister, Lockable,
org.hibernate.persister.entity.Queryable, InFlightEntityMappingType, EntityMutationTarget {
@ -3334,6 +3333,11 @@ public abstract class AbstractEntityPersister
}
}
/**
* Builds the EntityTableMapping descriptors for the tables mapped by this entity.
*
* @see #visitMutabilityOrderedTables
*/
protected EntityTableMapping[] buildTableMappings() {
final LinkedHashMap<String, TableMappingBuilder> tableBuilderMap = new LinkedHashMap<>();
@ -3403,10 +3407,28 @@ public abstract class AbstractEntityPersister
return list;
}
/**
* Visit details about each table for this entity, using "mutability ordering" -
* when inserting rows, the order we go through the tables to avoid foreign-key
* problems amongst the entity's group of tables.
*
* Used while {@linkplain #buildTableMappings building} the {@linkplain EntityTableMapping table-mapping}
* descriptors for each table.
*
* @see #forEachMutableTable
* @see #forEachMutableTableReverse
*/
protected abstract void visitMutabilityOrderedTables(MutabilityOrderedTableConsumer consumer);
/**
* Consumer for processing table details. Used while {@linkplain #buildTableMappings() building}
* the {@link EntityTableMapping} descriptors.
*/
interface MutabilityOrderedTableConsumer {
void consume(String tableExpression, int relativePosition, Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier);
void consume(
String tableExpression,
int relativePosition,
Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier);
}
private void collectAttributesIndexesForTable(int naturalTableIndex, Consumer<Integer> indexConsumer) {

View File

@ -7,6 +7,7 @@
package org.hibernate.persister.entity;
import org.hibernate.QueryException;
import org.hibernate.Remove;
import org.hibernate.persister.collection.CompositeElementPropertyMapping;
import org.hibernate.type.Type;
@ -21,14 +22,11 @@ import org.hibernate.type.Type;
* of how Hibernate originally understood composites (embeddables) internally. That is in the process of changing
* as Hibernate has added {@link CompositeElementPropertyMapping}
*
* todo (6.0) : move to {@link org.hibernate.persister.spi} - that is its more logical home. AFAIK this
* has never been documented as a public API
*
* todo (6.0) : re-word these Javadocs
*
* @author Gavin King
* @author Steve Ebersole
*/
@Deprecated(since = "6", forRemoval = true)
@Remove
public interface PropertyMapping {
// /**

View File

@ -12,7 +12,7 @@ package org.hibernate.persister.entity;
*
* @author Gavin King
*
* @deprecated See {@link org.hibernate.metamodel.mapping.Queryable}
* @deprecated See {@link org.hibernate.metamodel.mapping.ModelPartContainer}
*/
@Deprecated(since = "6.0")
public interface Queryable extends Loadable, PropertyMapping, Joinable {

View File

@ -14,7 +14,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.model.domain.DomainType;
@ -94,7 +93,7 @@ public class AnonymousTupleEmbeddedEntityIdentifierMapping extends AnonymousTupl
}
@Override
public MappingType getMappedType() {
public EmbeddableMappingType getMappedType() {
return this;
}

View File

@ -14,7 +14,6 @@ import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.internal.IdClassEmbeddable;
@ -90,7 +89,7 @@ public class AnonymousTupleNonAggregatedEntityIdentifierMapping extends Anonymou
}
@Override
public MappingType getMappedType() {
public EmbeddableMappingType getMappedType() {
return this;
}

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.query.derived;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -29,7 +28,6 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
@ -45,7 +43,6 @@ import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.cte.CteColumn;
import org.hibernate.sql.ast.tree.from.LazyTableGroup;
import org.hibernate.sql.ast.tree.from.PluralTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup;
@ -300,6 +297,14 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
return modelParts.get( name );
}
@Override
public void forEachSubPart(IndexedConsumer<ModelPart> consumer, EntityMappingType treatTarget) {
int i = 0;
for ( Map.Entry<String, ModelPart> entry : modelParts.entrySet() ) {
consumer.accept( i++, entry.getValue() );
}
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
for ( ModelPart modelPart : modelParts.values() ) {

View File

@ -4059,7 +4059,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final ToOneAttributeMapping toOneMapping = (ToOneAttributeMapping) subPart;
final ForeignKeyDescriptor fkDescriptor = toOneMapping.getForeignKeyDescriptor();
final TableReference tableReference = tableGroup.resolveTableReference( fkDescriptor.getTable( toOneMapping.getSideNature() ) );
final TableReference tableReference = tableGroup.resolveTableReference( toOneMapping.getContainingTableExpression() );
final ModelPart fkKeyPart = fkDescriptor.getPart( toOneMapping.getSideNature() );
if ( fkKeyPart instanceof BasicValuedModelPart ) {

View File

@ -6,8 +6,6 @@
*/
package org.hibernate.spi;
import java.util.function.BiFunction;
/**
* Hibernate often deals with compound names/paths. This interface defines a
* standard way of interacting with them
@ -51,14 +49,4 @@ public interface DotIdentifierSequence {
return getParent() == null;
}
default <T> T resolve(T base, BiFunction<T, String, T> baseResolver, BiFunction<T, String, T> resolver) {
final T result;
if ( getParent() == null ) {
result = baseResolver.apply( base, getLocalName() );
}
else {
result = resolver.apply( getParent().resolve( base, baseResolver, resolver ), getLocalName() );
}
return result;
}
}