diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java index 8d29c302e6..b8caa59de4 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java @@ -741,7 +741,7 @@ private HqlInterpretation interpretHql(String hql, Class resultType) { .resolveHqlInterpretation( hql, resultType, - s -> queryEngine.getHqlTranslator().translate( hql, resultType ) + queryEngine.getHqlTranslator() ); } 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 bf8fef9b1c..454900f94b 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 @@ -9,10 +9,10 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; -import jakarta.persistence.Tuple; import org.hibernate.internal.util.collections.BoundedConcurrentHashMap; import org.hibernate.query.QueryLogging; +import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.spi.HqlInterpretation; import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.ParameterMetadataImplementor; @@ -40,7 +40,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; @@ -104,18 +104,29 @@ public HqlInterpretation resolveHqlInterpretation( String queryString, Class expectedResultType, Function> creator) { + return resolveHqlInterpretation( queryString, expectedResultType, new HqlTranslator() { + @Override + public SqmStatement translate(String hql, Class expectedResultType) { + //noinspection unchecked + return (SqmStatement) creator.apply( hql ); + } + } ); + } + + @Override + public HqlInterpretation resolveHqlInterpretation( + String queryString, + Class expectedResultType, + HqlTranslator translator) { log.tracef( "QueryPlan#resolveHqlInterpretation( `%s` )", queryString ); - final String cacheKey; - if ( expectedResultType != null - && ( expectedResultType.isArray() || Tuple.class.isAssignableFrom( expectedResultType ) ) ) { - cacheKey = "multi_" + queryString; + final Object cacheKey; + if ( expectedResultType != null ) { + cacheKey = new HqlInterpretationCacheKey( queryString, expectedResultType ); } else { cacheKey = queryString; } - - final HqlInterpretation existing = hqlInterpretationCache.get( cacheKey ); if ( existing != null ) { final StatisticsImplementor statistics = statisticsSupplier.get(); @@ -124,21 +135,28 @@ public HqlInterpretation resolveHqlInterpretation( } return existing; } - - final HqlInterpretation hqlInterpretation = createHqlInterpretation( queryString, creator, statisticsSupplier ); - hqlInterpretationCache.put( cacheKey, hqlInterpretation ); - return hqlInterpretation; + else { + final HqlInterpretation hqlInterpretation = createHqlInterpretation( + queryString, + expectedResultType, + translator, + statisticsSupplier + ); + hqlInterpretationCache.put( cacheKey, hqlInterpretation ); + return hqlInterpretation; + } } protected static HqlInterpretation createHqlInterpretation( String queryString, - Function> creator, + Class expectedResultType, + HqlTranslator translator, Supplier statisticsSupplier) { final StatisticsImplementor statistics = statisticsSupplier.get(); final boolean stats = statistics.isStatisticsEnabled(); final long startTime = ( stats ) ? System.nanoTime() : 0L; - final SqmStatement sqmStatement = creator.apply( queryString ); + final SqmStatement sqmStatement = translator.translate( queryString, expectedResultType ); final ParameterMetadataImplementor parameterMetadata; final DomainParameterXref domainParameterXref; @@ -188,4 +206,32 @@ public void close() { queryPlanCache.clear(); } + private static final class HqlInterpretationCacheKey { + private final String queryString; + private final Class expectedResultType; + + public HqlInterpretationCacheKey(String queryString, Class expectedResultType) { + this.queryString = queryString; + this.expectedResultType = expectedResultType; + } + + @Override + public boolean equals(Object o) { + if ( o.getClass() != HqlInterpretationCacheKey.class ) { + return false; + } + + final HqlInterpretationCacheKey that = (HqlInterpretationCacheKey) o; + return queryString.equals( that.queryString ) + && expectedResultType.equals( that.expectedResultType ); + } + + @Override + public int hashCode() { + int result = queryString.hashCode(); + result = 31 * result + expectedResultType.hashCode(); + return result; + } + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryInterpretationCache.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryInterpretationCache.java index c721156272..7d8038afea 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryInterpretationCache.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryInterpretationCache.java @@ -10,6 +10,7 @@ import java.util.function.Supplier; import org.hibernate.Incubating; +import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.sql.spi.ParameterInterpretation; import org.hibernate.query.sqm.tree.SqmStatement; @@ -35,8 +36,13 @@ default Key prepareForStore() { int getNumberOfCachedHqlInterpretations(); int getNumberOfCachedQueryPlans(); + @Deprecated(forRemoval = true) HqlInterpretation resolveHqlInterpretation(String queryString, Class expectedResultType, Function> creator); + default HqlInterpretation resolveHqlInterpretation(String queryString, Class expectedResultType, HqlTranslator translator) { + return resolveHqlInterpretation( queryString, expectedResultType, s -> translator.translate( queryString, expectedResultType ) ); + } + SelectQueryPlan resolveSelectQueryPlan(Key key, Supplier> creator); NonSelectQueryPlan getNonSelectQueryPlan(Key key);