HHH-16215 Composite primary key @IdClass attribute mapping is borrowed from the first OneToMany backref and cannot be set

This commit is contained in:
Andrea Boriero 2023-03-07 11:30:47 +01:00 committed by Christian Beikov
parent e1e0eb8968
commit c86d755d75
10 changed files with 53 additions and 69 deletions

View File

@ -688,6 +688,10 @@ public class LoaderSelectBuilder {
LoaderSqlAstCreationState creationState, LoaderSqlAstCreationState creationState,
ImmutableFetchList.Builder fetches) { ImmutableFetchList.Builder fetches) {
return (fetchable, isKeyFetchable) -> { return (fetchable, isKeyFetchable) -> {
if ( !fetchable.isSelectable() ) {
return;
}
final NavigablePath fetchablePath; final NavigablePath fetchablePath;
if ( isKeyFetchable ) { if ( isKeyFetchable ) {
@ -841,6 +845,7 @@ public class LoaderSelectBuilder {
// For non-join fetches, we reset the currentBagRole and set it to the previous value in the finally block // For non-join fetches, we reset the currentBagRole and set it to the previous value in the finally block
currentBagRole = null; currentBagRole = null;
} }
final Fetch fetch = fetchParent.generateFetchableFetch( final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable, fetchable,
fetchablePath, fetchablePath,

View File

@ -25,6 +25,8 @@ public interface AttributeMetadata {
boolean isUpdatable(); boolean isUpdatable();
boolean isSelectable();
boolean isIncludedInDirtyChecking(); boolean isIncludedInDirtyChecking();
boolean isIncludedInOptimisticLocking(); boolean isIncludedInOptimisticLocking();

View File

@ -348,6 +348,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
insertable, insertable,
updateable, updateable,
includeInOptimisticLocking, includeInOptimisticLocking,
true,
cascadeStyle cascadeStyle
); );

View File

@ -444,6 +444,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
insertable, insertable,
updateable, updateable,
includeInOptimisticLocking, includeInOptimisticLocking,
true,
cascadeStyle cascadeStyle
); );

View File

@ -370,6 +370,7 @@ public class MappingModelCreationHelper {
bootProperty.isInsertable(), bootProperty.isInsertable(),
bootProperty.isUpdateable(), bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked(), bootProperty.isOptimisticLocked(),
bootProperty.isSelectable(),
cascadeStyle cascadeStyle
); );
} }
@ -416,7 +417,7 @@ public class MappingModelCreationHelper {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public static AttributeMetadata getAttributeMetadata(PropertyAccess propertyAccess) { public static AttributeMetadata getAttributeMetadata(PropertyAccess propertyAccess) {
return new SimpleAttributeMetadata( propertyAccess, ImmutableMutabilityPlan.INSTANCE, false, true, false, false, null);// todo (6.0) : not sure if CascadeStyle=null is correct return new SimpleAttributeMetadata( propertyAccess, ImmutableMutabilityPlan.INSTANCE, false, true, false, false, true, null);// todo (6.0) : not sure if CascadeStyle=null is correct
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@ -605,6 +606,7 @@ public class MappingModelCreationHelper {
bootProperty.isInsertable(), bootProperty.isInsertable(),
bootProperty.isUpdateable(), bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked(), bootProperty.isOptimisticLocked(),
bootProperty.isSelectable(),
cascadeStyle cascadeStyle
); );

View File

@ -21,6 +21,7 @@ public final class SimpleAttributeMetadata implements AttributeMetadata {
private final boolean nullable; private final boolean nullable;
private final boolean insertable; private final boolean insertable;
private final boolean updateable; private final boolean updateable;
private final boolean selectable;
private final boolean includeInOptimisticLocking; private final boolean includeInOptimisticLocking;
private final CascadeStyle cascadeStyle; private final CascadeStyle cascadeStyle;
@ -36,14 +37,19 @@ public final class SimpleAttributeMetadata implements AttributeMetadata {
value.isNullable(), value.isNullable(),
bootProperty.isInsertable(), bootProperty.isInsertable(),
bootProperty.isUpdateable(), bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked() bootProperty.isOptimisticLocked(),
bootProperty.isSelectable()
); );
} }
public SimpleAttributeMetadata( public SimpleAttributeMetadata(
PropertyAccess propertyAccess, PropertyAccess propertyAccess,
MutabilityPlan mutabilityPlan, MutabilityPlan mutabilityPlan,
boolean nullable, boolean insertable, boolean updateable, boolean includeInOptimisticLocking) { boolean nullable,
boolean insertable,
boolean updateable,
boolean includeInOptimisticLocking,
boolean selectable) {
this( this(
propertyAccess, propertyAccess,
mutabilityPlan, mutabilityPlan,
@ -51,6 +57,7 @@ public final class SimpleAttributeMetadata implements AttributeMetadata {
insertable, insertable,
updateable, updateable,
includeInOptimisticLocking, includeInOptimisticLocking,
selectable,
CascadeStyles.NONE // default - but beware of comment on AttributeMetadata#getCascadeStyle having a TODO CascadeStyles.NONE // default - but beware of comment on AttributeMetadata#getCascadeStyle having a TODO
); );
} }
@ -62,12 +69,14 @@ public final class SimpleAttributeMetadata implements AttributeMetadata {
boolean insertable, boolean insertable,
boolean updateable, boolean updateable,
boolean includeInOptimisticLocking, boolean includeInOptimisticLocking,
boolean selectable,
CascadeStyle cascadeStyle) { CascadeStyle cascadeStyle) {
this.propertyAccess = propertyAccess; this.propertyAccess = propertyAccess;
this.mutabilityPlan = mutabilityPlan; this.mutabilityPlan = mutabilityPlan;
this.nullable = nullable; this.nullable = nullable;
this.insertable = insertable; this.insertable = insertable;
this.updateable = updateable; this.updateable = updateable;
this.selectable = selectable;
this.includeInOptimisticLocking = includeInOptimisticLocking; this.includeInOptimisticLocking = includeInOptimisticLocking;
this.cascadeStyle = cascadeStyle; this.cascadeStyle = cascadeStyle;
} }
@ -97,6 +106,11 @@ public final class SimpleAttributeMetadata implements AttributeMetadata {
return updateable; return updateable;
} }
@Override
public boolean isSelectable(){
return selectable;
}
@Override @Override
public boolean isIncludedInDirtyChecking() { public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct // todo (6.0) : do not believe this is correct

View File

@ -255,7 +255,6 @@ import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl; import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
import org.hibernate.sql.results.graph.internal.ImmutableFetchList; import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
@ -370,7 +369,6 @@ public abstract class AbstractEntityPersister
private final String[][] propertyColumnWriters; private final String[][] propertyColumnWriters;
private final boolean[][] propertyColumnUpdateable; private final boolean[][] propertyColumnUpdateable;
private final boolean[][] propertyColumnInsertable; private final boolean[][] propertyColumnInsertable;
private final boolean[] propertySelectable;
private final List<Integer> lobProperties; private final List<Integer> lobProperties;
@ -619,7 +617,6 @@ public abstract class AbstractEntityPersister
propertyColumnNames = new String[hydrateSpan][]; propertyColumnNames = new String[hydrateSpan][];
propertyColumnFormulaTemplates = new String[hydrateSpan][]; propertyColumnFormulaTemplates = new String[hydrateSpan][];
propertyColumnWriters = new String[hydrateSpan][]; propertyColumnWriters = new String[hydrateSpan][];
propertySelectable = new boolean[hydrateSpan];
propertyColumnUpdateable = new boolean[hydrateSpan][]; propertyColumnUpdateable = new boolean[hydrateSpan][];
propertyColumnInsertable = new boolean[hydrateSpan][]; propertyColumnInsertable = new boolean[hydrateSpan][];
@ -691,8 +688,6 @@ public abstract class AbstractEntityPersister
propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability(); propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability();
propertyColumnInsertable[i] = prop.getValue().getColumnInsertability(); propertyColumnInsertable[i] = prop.getValue().getColumnInsertability();
propertySelectable[i] = prop.isSelectable();
if ( prop.isLob() && dialect.forceLobAsLastValue() ) { if ( prop.isLob() && dialect.forceLobAsLastValue() ) {
lobPropertiesLocalCollector.add( i ); lobPropertiesLocalCollector.add( i );
} }
@ -1813,7 +1808,7 @@ public abstract class AbstractEntityPersister
throw new AssertionFailure("fetchTiming was null"); throw new AssertionFailure("fetchTiming was null");
} }
if ( isSelectable( fetchParent, fetchable ) ) { if ( fetchable.isSelectable() ) {
final Fetch fetch = fetchParent.generateFetchableFetch( final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable, fetchable,
fetchParent.resolveNavigablePath( fetchable ), fetchParent.resolveNavigablePath( fetchable ),
@ -1830,37 +1825,12 @@ public abstract class AbstractEntityPersister
return fetches.build(); return fetches.build();
} }
/**
* @deprecated use {@link Fetchable#isSelectable()} instead.
*/
@Deprecated
public boolean isSelectable(FetchParent fetchParent, Fetchable fetchable) { public boolean isSelectable(FetchParent fetchParent, Fetchable fetchable) {
if ( fetchParent instanceof EmbeddableResultGraphNode ) { return fetchable.isSelectable();
return true;
}
else {
final AttributeMapping attributeMapping = fetchable.asAttributeMapping();
if ( attributeMapping != null ) {
final int propertyNumber = attributeMapping.getStateArrayPosition();
if ( propertyNumber < propertySelectable.length ) {
return propertySelectable[propertyNumber];
}
else {
final ManagedMappingType declaringType = attributeMapping.getDeclaringType();
// try to check select-ability from the declaring type
if ( declaringType != this ) {
assert declaringType instanceof AbstractEntityPersister;
final AbstractEntityPersister subPersister = (AbstractEntityPersister) declaringType;
return subPersister.propertySelectable[propertyNumber];
}
else {
throw new IllegalArgumentException(
"Unrecognized fetchable [" + fetchable.getFetchableName() + "] at index "
+ propertyNumber + " for entity [" + getEntityName() + "]"
);
}
}
}
else {
return true;
}
}
} }
@Override @Override
@ -4162,7 +4132,7 @@ public abstract class AbstractEntityPersister
@Override @Override
public boolean isPropertySelectable(int propertyNumber) { public boolean isPropertySelectable(int propertyNumber) {
return propertySelectable[propertyNumber]; return getAttributeMapping( propertyNumber ).getAttributeMetadata().isSelectable();
} }
@Override @Override
@ -5424,7 +5394,8 @@ public abstract class AbstractEntityPersister
bootProperty.isOptional(), bootProperty.isOptional(),
bootProperty.isInsertable(), bootProperty.isInsertable(),
bootProperty.isUpdateable(), bootProperty.isUpdateable(),
bootProperty.isOptimisticLocked() bootProperty.isOptimisticLocked(),
bootProperty.isSelectable()
); );
return new DiscriminatedAssociationAttributeMapping( return new DiscriminatedAssociationAttributeMapping(

View File

@ -31,7 +31,6 @@ import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.internal.BasicValuedCollectionPart; import org.hibernate.metamodel.mapping.internal.BasicValuedCollectionPart;
import org.hibernate.metamodel.mapping.internal.CaseStatementDiscriminatorMappingImpl; import org.hibernate.metamodel.mapping.internal.CaseStatementDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.spi.EntityIdentifierNavigablePath; import org.hibernate.spi.EntityIdentifierNavigablePath;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy; import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
@ -460,9 +459,7 @@ public class DomainResultCreationStateImpl
private Consumer<Fetchable> createFetchableConsumer(FetchParent fetchParent, ImmutableFetchList.Builder fetches) { private Consumer<Fetchable> createFetchableConsumer(FetchParent fetchParent, ImmutableFetchList.Builder fetches) {
return fetchable -> { return fetchable -> {
final FetchableContainer parentMappingType = fetchParent.getReferencedMappingContainer(); if ( !fetchable.isSelectable() ) {
if ( parentMappingType instanceof AbstractEntityPersister
&& !( ( (AbstractEntityPersister) parentMappingType ).isSelectable( fetchParent, fetchable ) ) ) {
return; return;
} }
final String fetchableName = fetchable.getFetchableName(); final String fetchableName = fetchable.getFetchableName();

View File

@ -102,7 +102,6 @@ import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl;
import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.QueryLogging; import org.hibernate.query.QueryLogging;
@ -7130,6 +7129,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
private Fetch createFetch(FetchParent fetchParent, Fetchable fetchable, Boolean isKeyFetchable) { private Fetch createFetch(FetchParent fetchParent, Fetchable fetchable, Boolean isKeyFetchable) {
if ( !fetchable.isSelectable() ) {
return null;
}
final NavigablePath resolvedNavigablePath = fetchParent.resolveNavigablePath( fetchable ); final NavigablePath resolvedNavigablePath = fetchParent.resolveNavigablePath( fetchable );
final Map.Entry<Integer, List<SqlSelection>> sqlSelectionsToTrack = trackedFetchSelectionsForGroup.get( resolvedNavigablePath ); final Map.Entry<Integer, List<SqlSelection>> sqlSelectionsToTrack = trackedFetchSelectionsForGroup.get( resolvedNavigablePath );
final int sqlSelectionStartIndexForFetch; final int sqlSelectionStartIndexForFetch;
@ -7250,27 +7252,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
); );
lhs.addTableGroupJoin( tableGroupJoin ); lhs.addTableGroupJoin( tableGroupJoin );
// if ( fetchable instanceof PluralAttributeMapping ) {
// // apply restrictions
// ( (Restrictable) fetchable ).applyBaseRestrictions(
// tableGroupJoin::applyPredicate,
// tableGroupJoin.getJoinedGroup(),
// true,
// loadQueryInfluencers.getEnabledFilters(),
// null,
// getSqlAstCreationState()
// );
//
// ( (PluralAttributeMapping) fetchable ).applyBaseManyToManyRestrictions(
// tableGroupJoin::applyPredicate,
// tableGroupJoin.getJoinedGroup(),
// true,
// loadQueryInfluencers.getEnabledFilters(),
// null,
// getSqlAstCreationState()
// );
// }
// and return the joined group // and return the joined group
return tableGroupJoin.getJoinedGroup(); return tableGroupJoin.getJoinedGroup();
} }
@ -7426,11 +7407,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
// Base restrictions have already been applied if this is an explicit fetch // Base restrictions have already been applied if this is an explicit fetch
if ( !explicitFetch ) { if ( !explicitFetch ) {
final Joinable joinable = pluralAttributeMapping final Restrictable restrictable = pluralAttributeMapping
.getCollectionDescriptor() .getCollectionDescriptor()
.getCollectionType() .getCollectionType()
.getAssociatedJoinable( getCreationContext().getSessionFactory() ); .getAssociatedJoinable( getCreationContext().getSessionFactory() );
joinable.applyBaseRestrictions( restrictable.applyBaseRestrictions(
(predicate) -> addCollectionFilterPredicate( tableGroup.getNavigablePath(), predicate ), (predicate) -> addCollectionFilterPredicate( tableGroup.getNavigablePath(), predicate ),
tableGroup, tableGroup,
true, true,

View File

@ -89,4 +89,14 @@ public interface Fetchable extends ModelPart {
default AttributeMapping asAttributeMapping() { default AttributeMapping asAttributeMapping() {
return null; return null;
} }
default boolean isSelectable() {
final AttributeMapping attributeMapping = asAttributeMapping();
if ( attributeMapping != null ) {
return attributeMapping.getAttributeMetadata().isSelectable();
}
else {
return true;
}
}
} }