HHH-16569 Batch fetch leads to some collections to be wrongly initialized with empty due to wrong generated SQL
This commit is contained in:
parent
611fa48c9b
commit
57c2c6e926
|
@ -12,7 +12,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -29,7 +28,6 @@ import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer;
|
|||
* be sub-select fetched later during initialization
|
||||
*/
|
||||
public class SubselectFetch {
|
||||
private final EntityValuedModelPart entityModelPart;
|
||||
private final QuerySpec loadingSqlAst;
|
||||
private final TableGroup ownerTableGroup;
|
||||
private final List<JdbcParameter> loadingJdbcParameters;
|
||||
|
@ -37,13 +35,11 @@ public class SubselectFetch {
|
|||
private final Set<EntityKey> resultingEntityKeys;
|
||||
|
||||
public SubselectFetch(
|
||||
EntityValuedModelPart entityModelPart,
|
||||
QuerySpec loadingSqlAst,
|
||||
TableGroup ownerTableGroup,
|
||||
List<JdbcParameter> loadingJdbcParameters,
|
||||
JdbcParameterBindings loadingJdbcParameterBindings,
|
||||
Set<EntityKey> resultingEntityKeys) {
|
||||
this.entityModelPart = entityModelPart;
|
||||
this.loadingSqlAst = loadingSqlAst;
|
||||
this.ownerTableGroup = ownerTableGroup;
|
||||
this.loadingJdbcParameters = loadingJdbcParameters;
|
||||
|
@ -51,10 +47,6 @@ public class SubselectFetch {
|
|||
this.resultingEntityKeys = resultingEntityKeys;
|
||||
}
|
||||
|
||||
public EntityValuedModelPart getEntityModelPart() {
|
||||
return entityModelPart;
|
||||
}
|
||||
|
||||
public List<JdbcParameter> getLoadingJdbcParameters() {
|
||||
// todo (6.0) : do not believe this is needed
|
||||
// - see org.hibernate.loader.ast.internal.LoaderSelectBuilder.generateSelect(org.hibernate.engine.spi.SubselectFetch)
|
||||
|
@ -94,7 +86,7 @@ public class SubselectFetch {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SubselectFetch(" + entityModelPart.getEntityMappingType().getEntityName() + ")";
|
||||
return "SubselectFetch(" + ownerTableGroup.getNavigablePath() + ")";
|
||||
}
|
||||
|
||||
public static RegistrationHandler createRegistrationHandler(
|
||||
|
@ -140,7 +132,6 @@ public class SubselectFetch {
|
|||
public static class StandardRegistrationHandler implements RegistrationHandler {
|
||||
private final BatchFetchQueue batchFetchQueue;
|
||||
private final SelectStatement loadingSqlAst;
|
||||
private final TableGroup ownerTableGroup;
|
||||
private final List<JdbcParameter> loadingJdbcParameters;
|
||||
private final JdbcParameterBindings loadingJdbcParameterBindings;
|
||||
private final Map<NavigablePath, SubselectFetch> subselectFetches = new HashMap<>();
|
||||
|
@ -153,7 +144,6 @@ public class SubselectFetch {
|
|||
JdbcParameterBindings loadingJdbcParameterBindings) {
|
||||
this.batchFetchQueue = batchFetchQueue;
|
||||
this.loadingSqlAst = loadingSqlAst;
|
||||
this.ownerTableGroup = ownerTableGroup;
|
||||
this.loadingJdbcParameters = loadingJdbcParameters;
|
||||
this.loadingJdbcParameterBindings = loadingJdbcParameterBindings;
|
||||
}
|
||||
|
@ -167,9 +157,10 @@ public class SubselectFetch {
|
|||
final SubselectFetch subselectFetch = subselectFetches.computeIfAbsent(
|
||||
entry.getEntityInitializer().getNavigablePath(),
|
||||
navigablePath -> new SubselectFetch(
|
||||
null,
|
||||
loadingSqlAst.getQuerySpec(),
|
||||
ownerTableGroup,
|
||||
loadingSqlAst.getQuerySpec()
|
||||
.getFromClause()
|
||||
.findTableGroup( entry.getEntityInitializer().getNavigablePath() ),
|
||||
loadingJdbcParameters,
|
||||
loadingJdbcParameterBindings,
|
||||
new HashSet<>()
|
||||
|
@ -188,7 +179,7 @@ public class SubselectFetch {
|
|||
final NavigablePath entityInitializerParent = entry.getEntityInitializer().getNavigablePath().getParent();
|
||||
|
||||
// We want to add only the collections of the loading entities
|
||||
for ( DomainResult domainResult : loadingSqlAst.getDomainResultDescriptors() ) {
|
||||
for ( DomainResult<?> domainResult : loadingSqlAst.getDomainResultDescriptors() ) {
|
||||
if ( domainResult.getNavigablePath().equals( entityInitializerParent ) ) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1076,7 +1076,6 @@ public class LoaderSelectBuilder {
|
|||
// generate and apply the restriction
|
||||
applySubSelectRestriction(
|
||||
rootQuerySpec,
|
||||
rootNavigablePath,
|
||||
rootTableGroup,
|
||||
subselect,
|
||||
sqlAstCreationState
|
||||
|
@ -1107,7 +1106,6 @@ public class LoaderSelectBuilder {
|
|||
|
||||
private void applySubSelectRestriction(
|
||||
QuerySpec querySpec,
|
||||
NavigablePath rootNavigablePath,
|
||||
TableGroup rootTableGroup,
|
||||
SubselectFetch subselect,
|
||||
LoaderSqlAstCreationState sqlAstCreationState) {
|
||||
|
@ -1115,7 +1113,6 @@ public class LoaderSelectBuilder {
|
|||
|
||||
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
|
||||
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
|
||||
final NavigablePath navigablePath = rootNavigablePath.append( attributeMapping.getAttributeName() );
|
||||
|
||||
final Expression fkExpression;
|
||||
|
||||
|
@ -1124,7 +1121,8 @@ public class LoaderSelectBuilder {
|
|||
assert fkDescriptor instanceof SimpleForeignKeyDescriptor;
|
||||
final SimpleForeignKeyDescriptor simpleFkDescriptor = (SimpleForeignKeyDescriptor) fkDescriptor;
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
||||
navigablePath,
|
||||
null,
|
||||
fkDescriptor,
|
||||
simpleFkDescriptor.getContainingTableExpression()
|
||||
);
|
||||
fkExpression = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||
|
@ -1137,7 +1135,8 @@ public class LoaderSelectBuilder {
|
|||
fkDescriptor.forEachSelectable(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
||||
navigablePath,
|
||||
null,
|
||||
fkDescriptor,
|
||||
selection.getContainingTableExpression()
|
||||
);
|
||||
columnReferences.add(
|
||||
|
@ -1168,24 +1167,19 @@ public class LoaderSelectBuilder {
|
|||
SubselectFetch subselect,
|
||||
LoaderSqlAstCreationState creationState) {
|
||||
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
|
||||
|
||||
final QuerySpec subQuery = new QuerySpec( false );
|
||||
|
||||
final QuerySpec loadingSqlAst = subselect.getLoadingSqlAst();
|
||||
|
||||
// todo (6.0) : we need to find the owner's TableGroup in the `loadingSqlAst`
|
||||
final TableGroup ownerTableGroup = subselect.getOwnerTableGroup();
|
||||
|
||||
// transfer the from-clause
|
||||
loadingSqlAst.getFromClause().visitRoots( subQuery.getFromClause()::addRoot );
|
||||
|
||||
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver();
|
||||
final NavigablePath navigablePath = ownerTableGroup.getNavigablePath().append( attributeMapping.getAttributeName() );
|
||||
|
||||
fkDescriptor.visitTargetSelectables(
|
||||
(valuesPosition, selection) -> {
|
||||
// for each column, resolve a SqlSelection and add it to the sub-query select-clause
|
||||
final TableReference tableReference = ownerTableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = ownerTableGroup.resolveTableReference( null, fkDescriptor, selection.getContainingTableExpression() );
|
||||
final Expression expression = sqlExpressionResolver.resolveSqlExpression(
|
||||
tableReference,
|
||||
selection
|
||||
|
|
|
@ -12,6 +12,8 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
|
@ -224,6 +226,20 @@ public class FromClause implements SqlAstNode {
|
|||
return null;
|
||||
}
|
||||
|
||||
public TableGroup findTableGroup(NavigablePath navigablePath) {
|
||||
return queryTableGroups(
|
||||
tg -> {
|
||||
if ( navigablePath.equals( tg.getNavigablePath() ) ) {
|
||||
return tg;
|
||||
}
|
||||
if ( tg instanceof OneToManyTableGroup && navigablePath.getParent().equals( tg.getNavigablePath() ) ) {
|
||||
return ( (OneToManyTableGroup) tg ).getTableGroup( CollectionPart.Nature.fromName( navigablePath.getLocalName() ) );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlTreeWalker.visitFromClause( this );
|
||||
|
|
Loading…
Reference in New Issue