From de0dd8cda30f1f1d27bc57dbeac3f25492c7c137 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Mon, 31 Jan 2022 11:39:26 +0100 Subject: [PATCH] Copy DomainParameterXref on demand instead of recreating to avoid instance mismatch with ParameterMetadata --- .../QueryInterpretationCacheStandardImpl.java | 34 ++++--------------- .../spi/SimpleHqlInterpretationImpl.java | 2 +- .../sqm/internal/DomainParameterXref.java | 9 ++++- .../test/query/sqm/exec/ParameterTest.java | 29 ++++++++++++++++ 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java index 407fcfc432..8541dff1cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java @@ -39,7 +39,7 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation */ private final BoundedConcurrentHashMap queryPlanCache; - private final BoundedConcurrentHashMap hqlInterpretationCache; + private final BoundedConcurrentHashMap hqlInterpretationCache; private final BoundedConcurrentHashMap nativeQueryParamCache; private final Supplier statisticsSupplier; @@ -108,8 +108,8 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation final long startTime = ( stats ) ? System.nanoTime() : 0L; final DomainParameterXref domainParameterXref; - ImmutableHqlInterpretation immutableHqlInterpretation = hqlInterpretationCache.get( queryString ); - if ( immutableHqlInterpretation == null ) { + HqlInterpretation hqlInterpretation = hqlInterpretationCache.get( queryString ); + if ( hqlInterpretation == null ) { log.debugf( "Creating and caching HqlInterpretation - %s", queryString ); final SqmStatement sqmStatement = creator.apply( queryString ); final ParameterMetadataImplementor parameterMetadata; @@ -123,8 +123,8 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation parameterMetadata = new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ); } - immutableHqlInterpretation = new ImmutableHqlInterpretation( sqmStatement, parameterMetadata); - hqlInterpretationCache.put( queryString, immutableHqlInterpretation ); + hqlInterpretation = new SimpleHqlInterpretationImpl( sqmStatement, parameterMetadata, domainParameterXref ); + hqlInterpretationCache.put( queryString, hqlInterpretation ); if ( stats ) { final long endTime = System.nanoTime(); @@ -136,19 +136,9 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation if ( stats ) { statistics.queryPlanCacheHit( queryString ); } - - if ( immutableHqlInterpretation.sqmStatement.getSqmParameters().isEmpty() ) { - domainParameterXref = DomainParameterXref.empty(); - } - else { - domainParameterXref = DomainParameterXref.from( immutableHqlInterpretation.sqmStatement ); - } } - return new SimpleHqlInterpretationImpl( - immutableHqlInterpretation.sqmStatement, - immutableHqlInterpretation.parameterMetadata, - domainParameterXref); + return hqlInterpretation; } @Override @@ -179,16 +169,4 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation queryPlanCache.clear(); } - private static class ImmutableHqlInterpretation { - - private final SqmStatement sqmStatement; - private final ParameterMetadataImplementor parameterMetadata; - - public ImmutableHqlInterpretation( - SqmStatement sqmStatement, - ParameterMetadataImplementor parameterMetadata) { - this.sqmStatement = sqmStatement; - this.parameterMetadata = parameterMetadata; - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/SimpleHqlInterpretationImpl.java b/hibernate-core/src/main/java/org/hibernate/query/spi/SimpleHqlInterpretationImpl.java index 5cb63ca982..9e4f3324d7 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/SimpleHqlInterpretationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/SimpleHqlInterpretationImpl.java @@ -38,6 +38,6 @@ public class SimpleHqlInterpretationImpl implements HqlInterpretation { @Override public DomainParameterXref getDomainParameterXref() { - return domainParameterXref; + return domainParameterXref.copy(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java index 7984be14bc..13a3532446 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java @@ -163,6 +163,14 @@ public class DomainParameterXref { this.parameterResolutions = parameterResolutions; } + public DomainParameterXref copy() { + return new DomainParameterXref( + sqmParamsByQueryParam, + new IdentityHashMap<>( queryParamBySqmParam ), + parameterResolutions + ); + } + /** * Does this xref contain any parameters? */ @@ -256,5 +264,4 @@ public class DomainParameterXref { expansions.clear(); } - } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/exec/ParameterTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/exec/ParameterTest.java index a4b6cce0e7..7cbcc01ef8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/exec/ParameterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/exec/ParameterTest.java @@ -6,10 +6,16 @@ */ package org.hibernate.orm.test.query.sqm.exec; +import org.hibernate.query.spi.QueryImplementor; +import org.hibernate.query.spi.QueryParameterImplementor; +import org.hibernate.query.sqm.internal.DomainParameterXref; +import org.hibernate.query.sqm.internal.QuerySqmImpl; + import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -39,4 +45,27 @@ public class ParameterTest { } ); } + + @Test + public void testParametersWithQueryInterpretationCache(SessionFactoryScope scope) { + String query = "from SalesAssociate p where p.name.familiarName in :names"; + scope.inTransaction( + session -> { + QueryImplementor q = session.createQuery( query ); + DomainParameterXref xref = q.unwrap( QuerySqmImpl.class ).getDomainParameterXref(); + for ( QueryParameterImplementor p : xref.getQueryParameters().keySet() ) { + Assertions.assertTrue( q.getParameterMetadata().containsReference( p ) ); + } + } + ); + scope.inTransaction( + session -> { + QueryImplementor q = session.createQuery( query ); + DomainParameterXref xref = q.unwrap( QuerySqmImpl.class ).getDomainParameterXref(); + for ( QueryParameterImplementor p : xref.getQueryParameters().keySet() ) { + Assertions.assertTrue( q.getParameterMetadata().containsReference( p ) ); + } + } + ); + } }