Skip to content

Commit fab70dd

Browse files
committed
HHH-19685 Rework multi-table handling and non-select query plan code to allow caching and help Hibernate Reactive
1 parent 64ab956 commit fab70dd

File tree

49 files changed

+4772
-3828
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+4772
-3828
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,9 +1558,9 @@ else if ( modelPart instanceof VirtualModelPart ) {
15581558
}
15591559

15601560
public static Expression buildColumnReferenceExpression(
1561-
TableGroup tableGroup,
1561+
@Nullable TableGroup tableGroup,
15621562
ModelPart modelPart,
1563-
SqlExpressionResolver sqlExpressionResolver,
1563+
@Nullable SqlExpressionResolver sqlExpressionResolver,
15641564
SessionFactoryImplementor sessionFactory) {
15651565
final int jdbcTypeCount = modelPart.getJdbcTypeCount();
15661566
if ( modelPart instanceof EmbeddableValuedModelPart ) {
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.query.sqm.internal;
6+
7+
import org.checkerframework.checker.nullness.qual.Nullable;
8+
import org.hibernate.action.internal.BulkOperationCleanupAction;
9+
import org.hibernate.query.spi.DomainQueryExecutionContext;
10+
import org.hibernate.query.spi.NonSelectQueryPlan;
11+
import org.hibernate.query.sqm.mutation.spi.MultiTableHandler;
12+
import org.hibernate.query.sqm.mutation.spi.MultiTableHandlerBuildResult;
13+
import org.hibernate.query.sqm.tree.SqmDmlStatement;
14+
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
15+
16+
17+
/**
18+
* @since 7.1
19+
*/
20+
public abstract class AbstractMultiTableMutationQueryPlan<S extends SqmDmlStatement<?>, F> implements NonSelectQueryPlan {
21+
private final S statement;
22+
private final DomainParameterXref domainParameterXref;
23+
private final F strategy;
24+
25+
private volatile MultiTableHandler handler;
26+
27+
public AbstractMultiTableMutationQueryPlan(S statement, DomainParameterXref domainParameterXref, F strategy) {
28+
this.statement = statement;
29+
this.domainParameterXref = domainParameterXref;
30+
this.strategy = strategy;
31+
}
32+
33+
protected abstract MultiTableHandlerBuildResult buildHandler(
34+
S statement,
35+
DomainParameterXref domainParameterXref,
36+
F strategy,
37+
DomainQueryExecutionContext context);
38+
39+
@Override
40+
public int executeUpdate(DomainQueryExecutionContext context) {
41+
BulkOperationCleanupAction.schedule( context.getSession(), statement );
42+
final Interpretation interpretation = getInterpretation( context );
43+
return interpretation.handler().execute( interpretation.jdbcParameterBindings(), context );
44+
}
45+
46+
// For Hibernate Reactive
47+
protected S getStatement() {
48+
return statement;
49+
}
50+
51+
// For Hibernate Reactive
52+
protected Interpretation getInterpretation(DomainQueryExecutionContext context) {
53+
Interpretation builtInterpretation = null;
54+
MultiTableHandler localCopy = handler;
55+
56+
if ( localCopy == null ) {
57+
synchronized (this) {
58+
localCopy = handler;
59+
if ( localCopy == null ) {
60+
final MultiTableHandlerBuildResult buildResult = buildHandler(
61+
statement,
62+
domainParameterXref,
63+
strategy,
64+
context
65+
);
66+
builtInterpretation = new Interpretation(
67+
buildResult.multiTableHandler(),
68+
buildResult.firstJdbcParameterBindings()
69+
);
70+
localCopy = buildResult.multiTableHandler();
71+
handler = localCopy;
72+
}
73+
else {
74+
builtInterpretation = updateInterpretation( localCopy, context );
75+
}
76+
}
77+
}
78+
else {
79+
builtInterpretation = updateInterpretation( localCopy, context );
80+
}
81+
return builtInterpretation != null ? builtInterpretation
82+
: new Interpretation( localCopy, localCopy.createJdbcParameterBindings( context ) );
83+
}
84+
85+
private @Nullable Interpretation updateInterpretation(
86+
MultiTableHandler localCopy,
87+
DomainQueryExecutionContext context) {
88+
Interpretation builtInterpretation = null;
89+
90+
// If the translation depends on parameter bindings or it isn't compatible with the current query options,
91+
// we have to rebuild the JdbcSelect, which is still better than having to translate from SQM to SQL AST again
92+
if ( localCopy.dependsOnParameterBindings() ) {
93+
final JdbcParameterBindings jdbcParameterBindings = localCopy.createJdbcParameterBindings( context );
94+
// If the translation depends on the limit or lock options, we have to rebuild the JdbcSelect
95+
// We could avoid this by putting the lock options into the cache key
96+
if ( !localCopy.isCompatibleWith( jdbcParameterBindings, context.getQueryOptions() ) ) {
97+
final MultiTableHandlerBuildResult buildResult = buildHandler(
98+
statement,
99+
domainParameterXref,
100+
strategy,
101+
context
102+
);
103+
localCopy = buildResult.multiTableHandler();
104+
builtInterpretation = new Interpretation(
105+
buildResult.multiTableHandler(),
106+
buildResult.firstJdbcParameterBindings()
107+
);
108+
handler = localCopy;
109+
}
110+
else {
111+
builtInterpretation = new Interpretation( localCopy, jdbcParameterBindings );
112+
}
113+
}
114+
return builtInterpretation;
115+
}
116+
117+
// For Hibernate Reactive
118+
protected record Interpretation(
119+
MultiTableHandler handler,
120+
JdbcParameterBindings jdbcParameterBindings
121+
) {}
122+
123+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.query.sqm.internal;
6+
7+
import org.hibernate.metamodel.mapping.MappingModelExpressible;
8+
import org.hibernate.query.spi.QueryParameterImplementor;
9+
import org.hibernate.query.sqm.tree.expression.SqmParameter;
10+
import org.hibernate.sql.ast.tree.Statement;
11+
import org.hibernate.sql.exec.spi.JdbcOperationQuery;
12+
import org.hibernate.sql.exec.spi.JdbcParametersList;
13+
14+
import java.util.List;
15+
import java.util.Map;
16+
17+
/**
18+
* @since 7.1
19+
*/
20+
public record CacheableSqmInterpretation<S extends Statement, J extends JdbcOperationQuery>(
21+
S statement,
22+
J jdbcOperation,
23+
Map<QueryParameterImplementor<?>, Map<SqmParameter<?>, List<JdbcParametersList>>> jdbcParamsXref,
24+
Map<SqmParameter<?>, MappingModelExpressible<?>> sqmParameterMappingModelTypes) {
25+
26+
}

0 commit comments

Comments
 (0)