18
18
import org .hibernate .engine .spi .SharedSessionContractImplementor ;
19
19
import org .hibernate .engine .spi .SubselectFetch ;
20
20
import org .hibernate .internal .EmptyScrollableResults ;
21
+ import org .hibernate .internal .util .MutableObject ;
21
22
import org .hibernate .metamodel .mapping .MappingModelExpressible ;
22
23
import org .hibernate .query .QueryTypeMismatchException ;
23
24
import org .hibernate .query .TupleTransformer ;
24
25
import org .hibernate .query .spi .DomainQueryExecutionContext ;
25
26
import org .hibernate .query .spi .QueryOptions ;
26
- import org .hibernate .query .spi .QueryParameterImplementor ;
27
27
import org .hibernate .query .spi .ScrollableResultsImplementor ;
28
28
import org .hibernate .query .spi .SelectQueryPlan ;
29
29
import org .hibernate .query .sqm .spi .SqmParameterMappingModelResolutionAccess ;
@@ -79,7 +79,7 @@ public class ConcreteSqmSelectQueryPlan<R> implements SelectQueryPlan<R> {
79
79
private final SqmInterpreter <List <R >, Void > listInterpreter ;
80
80
private final SqmInterpreter <ScrollableResultsImplementor <R >, ScrollMode > scrollInterpreter ;
81
81
82
- private volatile CacheableSqmInterpretation cacheableSqmInterpretation ;
82
+ private volatile CacheableSqmInterpretation < SelectStatement , JdbcOperationQuerySelect > cacheableSqmInterpretation ;
83
83
84
84
public ConcreteSqmSelectQueryPlan (
85
85
SqmSelectStatement <?> sqm ,
@@ -97,16 +97,16 @@ public ConcreteSqmSelectQueryPlan(
97
97
: ListResultsConsumer .UniqueSemantic .ALLOW ;
98
98
this .executeQueryInterpreter = (resultsConsumer , executionContext , sqmInterpretation , jdbcParameterBindings ) -> {
99
99
final SharedSessionContractImplementor session = executionContext .getSession ();
100
- final JdbcOperationQuerySelect jdbcSelect = sqmInterpretation .getJdbcSelect ();
100
+ final JdbcOperationQuerySelect jdbcSelect = sqmInterpretation .jdbcOperation ();
101
101
try {
102
102
final SubselectFetch .RegistrationHandler subSelectFetchKeyHandler = SubselectFetch .createRegistrationHandler (
103
103
session .getPersistenceContext ().getBatchFetchQueue (),
104
- sqmInterpretation .selectStatement ,
104
+ sqmInterpretation .statement () ,
105
105
JdbcParametersList .empty (),
106
106
jdbcParameterBindings
107
107
);
108
108
session .autoFlushIfRequired ( jdbcSelect .getAffectedTableNames (), true );
109
- final Expression fetchExpression = sqmInterpretation .selectStatement .getQueryPart ()
109
+ final Expression fetchExpression = sqmInterpretation .statement () .getQueryPart ()
110
110
.getFetchClauseExpression ();
111
111
final int resultCountEstimate = fetchExpression != null
112
112
? interpretIntExpression ( fetchExpression , jdbcParameterBindings )
@@ -127,17 +127,17 @@ public ConcreteSqmSelectQueryPlan(
127
127
};
128
128
this .listInterpreter = (unused , executionContext , sqmInterpretation , jdbcParameterBindings ) -> {
129
129
final SharedSessionContractImplementor session = executionContext .getSession ();
130
- final JdbcOperationQuerySelect jdbcSelect = sqmInterpretation .getJdbcSelect ();
130
+ final JdbcOperationQuerySelect jdbcSelect = sqmInterpretation .jdbcOperation ();
131
131
try {
132
132
final SubselectFetch .RegistrationHandler subSelectFetchKeyHandler = SubselectFetch .createRegistrationHandler (
133
133
session .getPersistenceContext ().getBatchFetchQueue (),
134
- sqmInterpretation .selectStatement ,
134
+ sqmInterpretation .statement () ,
135
135
JdbcParametersList .empty (),
136
136
jdbcParameterBindings
137
137
);
138
138
session .autoFlushIfRequired ( jdbcSelect .getAffectedTableNames (), true );
139
139
final Expression fetchExpression =
140
- sqmInterpretation .selectStatement .getQueryPart ()
140
+ sqmInterpretation .statement () .getQueryPart ()
141
141
.getFetchClauseExpression ();
142
142
final int resultCountEstimate = fetchExpression != null
143
143
? interpretIntExpression ( fetchExpression , jdbcParameterBindings )
@@ -160,7 +160,7 @@ public ConcreteSqmSelectQueryPlan(
160
160
161
161
this .scrollInterpreter = (scrollMode , executionContext , sqmInterpretation , jdbcParameterBindings ) -> {
162
162
final SharedSessionContractImplementor session = executionContext .getSession ();
163
- final JdbcOperationQuerySelect jdbcSelect = sqmInterpretation .getJdbcSelect ();
163
+ final JdbcOperationQuerySelect jdbcSelect = sqmInterpretation .jdbcOperation ();
164
164
try {
165
165
// final SubselectFetch.RegistrationHandler subSelectFetchKeyHandler = SubselectFetch.createRegistrationHandler(
166
166
// executionContext.getSession().getPersistenceContext().getBatchFetchQueue(),
@@ -173,7 +173,7 @@ public ConcreteSqmSelectQueryPlan(
173
173
session .getFactory ().getJdbcServices ().getJdbcSelectExecutor ();
174
174
session .autoFlushIfRequired ( jdbcSelect .getAffectedTableNames (), true );
175
175
final Expression fetchExpression =
176
- sqmInterpretation .selectStatement .getQueryPart ()
176
+ sqmInterpretation .statement () .getQueryPart ()
177
177
.getFetchClauseExpression ();
178
178
final int resultCountEstimate = fetchExpression != null
179
179
? interpretIntExpression ( fetchExpression , jdbcParameterBindings )
@@ -401,7 +401,7 @@ private <T, X> T withCacheableSqmInterpretation(DomainQueryExecutionContext exec
401
401
// to protect access. However, synchronized is much simpler here. We will verify
402
402
// during throughput testing whether this is an issue and consider changes then
403
403
404
- CacheableSqmInterpretation localCopy = cacheableSqmInterpretation ;
404
+ CacheableSqmInterpretation < SelectStatement , JdbcOperationQuerySelect > localCopy = cacheableSqmInterpretation ;
405
405
JdbcParameterBindings jdbcParameterBindings = null ;
406
406
407
407
executionContext .getSession ().autoPreFlush ();
@@ -410,23 +410,23 @@ private <T, X> T withCacheableSqmInterpretation(DomainQueryExecutionContext exec
410
410
synchronized ( this ) {
411
411
localCopy = cacheableSqmInterpretation ;
412
412
if ( localCopy == null ) {
413
- localCopy = buildCacheableSqmInterpretation ( sqm , domainParameterXref , executionContext );
414
- jdbcParameterBindings = localCopy . firstParameterBindings ;
415
- localCopy . firstParameterBindings = null ;
413
+ final MutableObject < JdbcParameterBindings > mutableValue = new MutableObject <>( );
414
+ localCopy = buildInterpretation ( sqm , domainParameterXref , executionContext , mutableValue ) ;
415
+ jdbcParameterBindings = mutableValue . get () ;
416
416
cacheableSqmInterpretation = localCopy ;
417
417
}
418
418
else {
419
419
// If the translation depends on parameter bindings or it isn't compatible with the current query options,
420
420
// we have to rebuild the JdbcSelect, which is still better than having to translate from SQM to SQL AST again
421
- if ( localCopy .jdbcSelect .dependsOnParameterBindings () ) {
421
+ if ( localCopy .jdbcOperation () .dependsOnParameterBindings () ) {
422
422
jdbcParameterBindings = createJdbcParameterBindings ( localCopy , executionContext );
423
423
}
424
424
// If the translation depends on the limit or lock options, we have to rebuild the JdbcSelect
425
425
// We could avoid this by putting the lock options into the cache key
426
- if ( !localCopy .jdbcSelect .isCompatibleWith ( jdbcParameterBindings , executionContext .getQueryOptions () ) ) {
427
- localCopy = buildCacheableSqmInterpretation ( sqm , domainParameterXref , executionContext );
428
- jdbcParameterBindings = localCopy . firstParameterBindings ;
429
- localCopy . firstParameterBindings = null ;
426
+ if ( !localCopy .jdbcOperation () .isCompatibleWith ( jdbcParameterBindings , executionContext .getQueryOptions () ) ) {
427
+ final MutableObject < JdbcParameterBindings > mutableValue = new MutableObject <>( );
428
+ localCopy = buildInterpretation ( sqm , domainParameterXref , executionContext , mutableValue ) ;
429
+ jdbcParameterBindings = mutableValue . get () ;
430
430
cacheableSqmInterpretation = localCopy ;
431
431
}
432
432
}
@@ -435,15 +435,15 @@ private <T, X> T withCacheableSqmInterpretation(DomainQueryExecutionContext exec
435
435
else {
436
436
// If the translation depends on parameter bindings or it isn't compatible with the current query options,
437
437
// we have to rebuild the JdbcSelect, which is still better than having to translate from SQM to SQL AST again
438
- if ( localCopy .jdbcSelect .dependsOnParameterBindings () ) {
438
+ if ( localCopy .jdbcOperation () .dependsOnParameterBindings () ) {
439
439
jdbcParameterBindings = createJdbcParameterBindings ( localCopy , executionContext );
440
440
}
441
441
// If the translation depends on the limit or lock options, we have to rebuild the JdbcSelect
442
442
// We could avoid this by putting the lock options into the cache key
443
- if ( !localCopy .jdbcSelect .isCompatibleWith ( jdbcParameterBindings , executionContext .getQueryOptions () ) ) {
444
- localCopy = buildCacheableSqmInterpretation ( sqm , domainParameterXref , executionContext );
445
- jdbcParameterBindings = localCopy . firstParameterBindings ;
446
- localCopy . firstParameterBindings = null ;
443
+ if ( !localCopy .jdbcOperation () .isCompatibleWith ( jdbcParameterBindings , executionContext .getQueryOptions () ) ) {
444
+ final MutableObject < JdbcParameterBindings > mutableValue = new MutableObject <>( );
445
+ localCopy = buildInterpretation ( sqm , domainParameterXref , executionContext , mutableValue ) ;
446
+ jdbcParameterBindings = mutableValue . get () ;
447
447
cacheableSqmInterpretation = localCopy ;
448
448
}
449
449
}
@@ -455,26 +455,27 @@ private <T, X> T withCacheableSqmInterpretation(DomainQueryExecutionContext exec
455
455
return interpreter .interpret ( context , executionContext , localCopy , jdbcParameterBindings );
456
456
}
457
457
458
- private JdbcParameterBindings createJdbcParameterBindings (CacheableSqmInterpretation sqmInterpretation , DomainQueryExecutionContext executionContext ) {
458
+ private JdbcParameterBindings createJdbcParameterBindings (CacheableSqmInterpretation < SelectStatement , JdbcOperationQuerySelect > sqmInterpretation , DomainQueryExecutionContext executionContext ) {
459
459
return SqmUtil .createJdbcParameterBindings (
460
460
executionContext .getQueryParameterBindings (),
461
461
domainParameterXref ,
462
- sqmInterpretation .getJdbcParamsXref (),
462
+ sqmInterpretation .jdbcParamsXref (),
463
463
new SqmParameterMappingModelResolutionAccess () {
464
464
//this is pretty ugly!
465
465
@ Override @ SuppressWarnings ("unchecked" )
466
466
public <T > MappingModelExpressible <T > getResolvedMappingModelType (SqmParameter <T > parameter ) {
467
- return (MappingModelExpressible <T >) sqmInterpretation .getSqmParameterMappingModelTypes ().get (parameter );
467
+ return (MappingModelExpressible <T >) sqmInterpretation .sqmParameterMappingModelTypes ().get (parameter );
468
468
}
469
469
},
470
470
executionContext .getSession ()
471
471
);
472
472
}
473
473
474
- private static CacheableSqmInterpretation buildCacheableSqmInterpretation (
474
+ private static CacheableSqmInterpretation < SelectStatement , JdbcOperationQuerySelect > buildInterpretation (
475
475
SqmSelectStatement <?> sqm ,
476
476
DomainParameterXref domainParameterXref ,
477
- DomainQueryExecutionContext executionContext ) {
477
+ DomainQueryExecutionContext executionContext ,
478
+ MutableObject <JdbcParameterBindings > firstJdbcParameterBindingsConsumer ) {
478
479
final SharedSessionContractImplementor session = executionContext .getSession ();
479
480
final SessionFactoryImplementor sessionFactory = session .getFactory ();
480
481
@@ -511,57 +512,23 @@ public <T> MappingModelExpressible<T> getResolvedMappingModelType(SqmParameter<T
511
512
},
512
513
session
513
514
);
514
-
515
- return new CacheableSqmInterpretation (
515
+ firstJdbcParameterBindingsConsumer . set ( jdbcParameterBindings );
516
+ return new CacheableSqmInterpretation <> (
516
517
sqmInterpretation .getSqlAst (),
517
518
selectTranslator .translate ( jdbcParameterBindings , executionContext .getQueryOptions () ),
518
519
jdbcParamsXref ,
519
- sqmInterpretation .getSqmParameterMappingModelTypeResolutions (),
520
- jdbcParameterBindings
520
+ sqmInterpretation .getSqmParameterMappingModelTypeResolutions ()
521
521
);
522
522
}
523
523
524
524
private interface SqmInterpreter <T , X > {
525
525
T interpret (
526
526
X context ,
527
527
DomainQueryExecutionContext executionContext ,
528
- CacheableSqmInterpretation sqmInterpretation ,
528
+ CacheableSqmInterpretation < SelectStatement , JdbcOperationQuerySelect > sqmInterpretation ,
529
529
JdbcParameterBindings jdbcParameterBindings );
530
530
}
531
531
532
- private static class CacheableSqmInterpretation {
533
- private final SelectStatement selectStatement ;
534
- private final JdbcOperationQuerySelect jdbcSelect ;
535
- private final Map <QueryParameterImplementor <?>, Map <SqmParameter <?>, List <JdbcParametersList >>> jdbcParamsXref ;
536
- private final Map <SqmParameter <?>, MappingModelExpressible <?>> sqmParameterMappingModelTypes ;
537
- private transient JdbcParameterBindings firstParameterBindings ;
538
-
539
- CacheableSqmInterpretation (
540
- SelectStatement selectStatement ,
541
- JdbcOperationQuerySelect jdbcSelect ,
542
- Map <QueryParameterImplementor <?>, Map <SqmParameter <?>, List <JdbcParametersList >>> jdbcParamsXref ,
543
- Map <SqmParameter <?>, MappingModelExpressible <?>> sqmParameterMappingModelTypes ,
544
- JdbcParameterBindings firstParameterBindings ) {
545
- this .selectStatement = selectStatement ;
546
- this .jdbcSelect = jdbcSelect ;
547
- this .jdbcParamsXref = jdbcParamsXref ;
548
- this .sqmParameterMappingModelTypes = sqmParameterMappingModelTypes ;
549
- this .firstParameterBindings = firstParameterBindings ;
550
- }
551
-
552
- JdbcOperationQuerySelect getJdbcSelect () {
553
- return jdbcSelect ;
554
- }
555
-
556
- Map <QueryParameterImplementor <?>, Map <SqmParameter <?>, List <JdbcParametersList >>> getJdbcParamsXref () {
557
- return jdbcParamsXref ;
558
- }
559
-
560
- public Map <SqmParameter <?>, MappingModelExpressible <?>> getSqmParameterMappingModelTypes () {
561
- return sqmParameterMappingModelTypes ;
562
- }
563
- }
564
-
565
532
private static class MySqmJdbcExecutionContextAdapter extends SqmJdbcExecutionContextAdapter {
566
533
private final SubselectFetch .RegistrationHandler subSelectFetchKeyHandler ;
567
534
private final String hql ;
0 commit comments