Skip to content

Commit

Permalink
HHH-15099 - Improve handling of associations marked with @NotFound
Browse files Browse the repository at this point in the history
- database snapshot handling
  • Loading branch information
sebersole committed Mar 5, 2022
1 parent ceb7df0 commit c5ac528
Show file tree
Hide file tree
Showing 24 changed files with 1,104 additions and 510 deletions.
Expand Up @@ -16,13 +16,11 @@
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.spi.NavigablePath;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.sql.FromClauseIndex;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
Expand All @@ -44,7 +42,6 @@
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.type.StandardBasicTypes;
Expand Down Expand Up @@ -145,44 +142,19 @@ class DatabaseSnapshotExecutor {
}
);

entityDescriptor.visitStateArrayContributors(
contributorMapping -> {
final NavigablePath navigablePath = rootPath.append( contributorMapping.getAttributeName() );
if ( contributorMapping instanceof SingularAttributeMapping ) {
if ( contributorMapping instanceof EntityAssociationMapping ) {
domainResults.add(
( (EntityAssociationMapping) contributorMapping ).createDelayedDomainResult(
navigablePath,
rootTableGroup,
null,
state
)
);
}
else {
domainResults.add(
contributorMapping.createDomainResult(
navigablePath,
rootTableGroup,
null,
state
)
);
}
}
else {
// TODO: Instead use a delayed collection result? Or will we remove this when redesigning this
//noinspection unchecked
domainResults.add(
new BasicResult(
0,
null,
contributorMapping.getJavaType()
)
);
}
}
);

entityDescriptor.visitStateArrayContributors( (contributorMapping) -> {
final NavigablePath navigablePath = rootPath.append( contributorMapping.getAttributeName() );
domainResults.add(
contributorMapping.createSnapshotDomainResult(
navigablePath,
rootTableGroup,
null,
state
)
);
} );

final SelectStatement selectStatement = new SelectStatement( rootQuerySpec, domainResults );

final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
Expand Down
Expand Up @@ -7,6 +7,7 @@
package org.hibernate.metamodel.mapping;

import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.sql.results.graph.DatabaseSnapshotContributor;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.tuple.ValueGeneration;
import org.hibernate.type.descriptor.java.MutabilityPlan;
Expand All @@ -17,7 +18,8 @@
*
* @author Steve Ebersole
*/
public interface AttributeMapping extends ModelPart, ValueMapping, Fetchable, PropertyBasedMapping, MutabilityPlanExposer {
public interface AttributeMapping
extends ModelPart, ValueMapping, Fetchable, DatabaseSnapshotContributor, PropertyBasedMapping, MutabilityPlanExposer {
/**
* The name of the mapped attribute
*/
Expand Down
Expand Up @@ -6,11 +6,7 @@
*/
package org.hibernate.metamodel.mapping;

import org.hibernate.query.spi.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;

/**
* Commonality between `many-to-one`, `one-to-one` and `any`, as well as entity-valued collection elements and map-keys
Expand All @@ -35,13 +31,4 @@ default String getFetchableName() {
default boolean incrementFetchDepth(){
return true;
}

/**
* Create a delayed DomainResult for a specific reference to this ModelPart.
*/
<T> DomainResult<T> createDelayedDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState);
}
Expand Up @@ -20,8 +20,11 @@
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.basic.BasicResult;

/**
* Mapping of a plural (collection-valued) attribute
Expand Down Expand Up @@ -68,6 +71,16 @@ default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappin
fetchableConsumer.accept( getElementDescriptor() );
}

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
default <T> DomainResult<T> createSnapshotDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState) {
return new BasicResult( 0, null, getJavaType() );
}

String getSeparateCollectionTable();

boolean isBidirectionalAttributeName(NavigablePath fetchablePath, ToOneAttributeMapping modelPart);
Expand Down
Expand Up @@ -73,6 +73,8 @@
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;

import static java.util.Objects.requireNonNullElse;

/**
* @author Steve Ebersole
*/
Expand Down Expand Up @@ -380,15 +382,6 @@ public ModelPart getKeyTargetMatchPart() {
: fkTargetModelPart;
}

@Override
public <T> DomainResult<T> createDelayedDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}

@Override
public JavaType<?> getJavaType() {
return getEntityMappingType().getJavaType();
Expand Down Expand Up @@ -583,13 +576,8 @@ public TableGroupJoin createTableGroupJoin(
SqlExpressionResolver sqlExpressionResolver,
FromClauseAccess fromClauseAccess,
SqlAstCreationContext creationContext) {
final SqlAstJoinType joinType;
if ( requestedJoinType == null ) {
joinType = SqlAstJoinType.INNER;
}
else {
joinType = requestedJoinType;
}
final SqlAstJoinType joinType = requireNonNullElse( requestedJoinType, SqlAstJoinType.INNER );

if ( collectionDescriptor.isOneToMany() && nature == Nature.ELEMENT ) {
// If this is a one-to-many, the element part is already available, so we return a TableGroupJoin "hull"
return new TableGroupJoin(
Expand Down Expand Up @@ -645,15 +633,10 @@ public LazyTableGroup createRootTableGroupJoin(
SqlExpressionResolver sqlExpressionResolver,
FromClauseAccess fromClauseAccess,
SqlAstCreationContext creationContext) {
final SqlAstJoinType joinType;
if ( requestedJoinType == null ) {
joinType = SqlAstJoinType.INNER;
}
else {
joinType = requestedJoinType;
}
final SqlAstJoinType joinType = requireNonNullElse( requestedJoinType, SqlAstJoinType.INNER );
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
final boolean canUseInnerJoin = joinType == SqlAstJoinType.INNER || lhs.canUseInnerJoins();

final LazyTableGroup lazyTableGroup = new LazyTableGroup(
canUseInnerJoin,
navigablePath,
Expand All @@ -670,7 +653,7 @@ public LazyTableGroup createRootTableGroupJoin(
(np, tableExpression) -> {
NavigablePath path = np.getParent();
// Fast path
if ( path != null && navigablePath.equals( path ) ) {
if ( navigablePath.equals( path ) ) {
return targetKeyPropertyNames.contains( np.getUnaliasedLocalName() )
&& fkDescriptor.getKeyTable().equals( tableExpression );
}
Expand All @@ -681,7 +664,7 @@ public LazyTableGroup createRootTableGroupJoin(
sb.insert( 0, path.getUnaliasedLocalName() );
path = path.getParent();
}
return path != null && navigablePath.equals( path )
return navigablePath.equals( path )
&& targetKeyPropertyNames.contains( sb.toString() )
&& fkDescriptor.getKeyTable().equals( tableExpression );
},
Expand Down

0 comments on commit c5ac528

Please sign in to comment.