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 b0e9d24e98..ac3d5da8ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java @@ -620,11 +620,11 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont throw exceptionConverter.convert( new IllegalArgumentException( "No query defined for that name [" + name + "]" ) ); } - protected QueryImpl createQuery(NamedQueryDefinition queryDefinition) { + protected QueryImplementor createQuery(NamedQueryDefinition queryDefinition) { String queryString = queryDefinition.getQueryString(); final QueryImpl query = new QueryImpl( this, - getQueryPlan( queryString, false ), + getQueryPlan( queryString, false ).getParameterMetadata(), queryString ); query.setHibernateFlushMode( queryDefinition.getFlushMode() ); @@ -693,7 +693,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont } @Override - public QueryImpl createQuery(String queryString) { + public QueryImplementor createQuery(String queryString) { checkOpen(); checkTransactionSynchStatus(); delayedAfterCompletion(); @@ -701,7 +701,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont try { final QueryImpl query = new QueryImpl( this, - getQueryPlan( queryString, false ), + getQueryPlan( queryString, false ).getParameterMetadata(), queryString ); query.setComment( queryString ); @@ -726,7 +726,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont try { // do the translation - final QueryImpl query = createQuery( queryString ); + final QueryImplementor query = createQuery( queryString ); resultClassChecking( resultClass, query ); return query; } @@ -736,10 +736,13 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont } @SuppressWarnings({"unchecked", "WeakerAccess", "StatementWithEmptyBody"}) - protected void resultClassChecking(Class resultClass, QueryImpl hqlQuery) { + protected void resultClassChecking(Class resultClass, org.hibernate.Query hqlQuery) { // make sure the query is a select -> HHH-7192 - HQLQueryPlan queryPlan = hqlQuery.getQueryPlan(); - + final HQLQueryPlan queryPlan = getFactory().getQueryPlanCache().getHQLQueryPlan( + hqlQuery.getQueryString(), + false, + getLoadQueryInfluencers().getEnabledFilters() + ); if ( queryPlan.getTranslators()[0].isManipulationStatement() ) { throw new IllegalArgumentException( "Update/delete queries cannot be typed" ); } @@ -815,7 +818,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont @SuppressWarnings({"WeakerAccess", "unchecked"}) protected QueryImplementor createQuery(NamedQueryDefinition namedQueryDefinition, Class resultType) { - final QueryImpl query = createQuery( namedQueryDefinition ); + final QueryImplementor query = createQuery( namedQueryDefinition ); if ( resultType != null ) { resultClassChecking( resultType, query ); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index c681c7a108..e52e6060de 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -1620,7 +1620,7 @@ public final class SessionImpl queryParameters.validateParameters(); HQLQueryPlan plan = queryParameters.getQueryPlan(); - if ( plan == null || !plan.isShallow() ) { + if ( plan == null ) { plan = getQueryPlan( query, true ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/Query.java b/hibernate-core/src/main/java/org/hibernate/query/Query.java index b75c0d2eff..e117152e21 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/Query.java +++ b/hibernate-core/src/main/java/org/hibernate/query/Query.java @@ -34,7 +34,6 @@ import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; -import org.hibernate.engine.query.spi.HQLQueryPlan; import org.hibernate.graph.Graph; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java index 4650c5d92a..f637cbfcd2 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java @@ -56,7 +56,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.TypedValue; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; -import org.hibernate.graph.internal.RootGraphImpl; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.hql.internal.QueryExecutionRequestException; import org.hibernate.internal.EmptyScrollableResults; @@ -65,6 +64,7 @@ import org.hibernate.internal.HEMLogging; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.TypedParameterValue; +import org.hibernate.graph.internal.RootGraphImpl; import org.hibernate.jpa.internal.util.CacheModeHelper; import org.hibernate.jpa.internal.util.ConfigurationHelper; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; @@ -1376,8 +1376,8 @@ public abstract class AbstractProducedQuery implements QueryImplementor { ); } - QueryParameters queryParameters = new QueryParameters( - getQueryParameterBindings(), + QueryParameters queryParameters = new QueryParameters( + getQueryParameterBindings(), getLockOptions(), queryOptions, true, @@ -1392,24 +1392,13 @@ public abstract class AbstractProducedQuery implements QueryImplementor { optionalId, resultTransformer ); - - appendQueryPlanToQueryParameters( hql, queryParameters, entityGraphHintedQueryPlan ); - + queryParameters.setQueryPlan( entityGraphHintedQueryPlan ); if ( passDistinctThrough != null ) { queryParameters.setPassDistinctThrough( passDistinctThrough ); } return queryParameters; } - protected void appendQueryPlanToQueryParameters( - String hql, - QueryParameters queryParameters, - HQLQueryPlan queryPlan) { - if ( queryPlan != null ) { - queryParameters.setQueryPlan( queryPlan ); - } - } - public QueryParameters getQueryParameters() { final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() ); return makeQueryParametersForExecution( expandedQuery ); @@ -1694,7 +1683,7 @@ public abstract class AbstractProducedQuery implements QueryImplementor { : defaultType; } - protected boolean isSelect() { + private boolean isSelect() { return getProducer().getFactory().getQueryPlanCache() .getHQLQueryPlan( getQueryString(), false, Collections.emptyMap() ) .isSelect(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryImpl.java index 35d8ad55dd..cda7388a8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryImpl.java @@ -6,10 +6,8 @@ */ package org.hibernate.query.internal; -import org.hibernate.engine.query.spi.HQLQueryPlan; -import org.hibernate.engine.query.spi.ReturnMetadata; -import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.query.ParameterMetadata; import org.hibernate.query.Query; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.type.Type; @@ -20,19 +18,16 @@ import org.hibernate.type.Type; public class QueryImpl extends AbstractProducedQuery implements Query { private final String queryString; - private final HQLQueryPlan hqlQueryPlan; - private final QueryParameterBindingsImpl queryParameterBindings; public QueryImpl( SharedSessionContractImplementor producer, - HQLQueryPlan hqlQueryPlan, + ParameterMetadata parameterMetadata, String queryString) { - super( producer, hqlQueryPlan.getParameterMetadata() ); - this.hqlQueryPlan = hqlQueryPlan; + super( producer, parameterMetadata ); this.queryString = queryString; this.queryParameterBindings = QueryParameterBindingsImpl.from( - hqlQueryPlan.getParameterMetadata(), + parameterMetadata, producer.getFactory(), producer.isQueryParametersValidationEnabled() ); @@ -48,10 +43,6 @@ public class QueryImpl extends AbstractProducedQuery implements Query { return queryString; } - public HQLQueryPlan getQueryPlan() { - return hqlQueryPlan; - } - @Override protected boolean isNativeQuery() { return false; @@ -59,14 +50,12 @@ public class QueryImpl extends AbstractProducedQuery implements Query { @Override public Type[] getReturnTypes() { - final ReturnMetadata metadata = hqlQueryPlan.getReturnMetadata(); - return metadata == null ? null : metadata.getReturnTypes(); + return getProducer().getFactory().getReturnTypes( queryString ); } @Override public String[] getReturnAliases() { - final ReturnMetadata metadata = hqlQueryPlan.getReturnMetadata(); - return metadata == null ? null : metadata.getReturnAliases(); + return getProducer().getFactory().getReturnAliases( queryString ); } @Override @@ -78,22 +67,4 @@ public class QueryImpl extends AbstractProducedQuery implements Query { public Query setEntity(String name, Object val) { return setParameter( name, val, getProducer().getFactory().getTypeHelper().entity( resolveEntityName( val ) ) ); } - - @Override - protected boolean isSelect() { - return hqlQueryPlan.isSelect(); - } - - @Override - protected void appendQueryPlanToQueryParameters( - String hql, - QueryParameters queryParameters, - HQLQueryPlan queryPlan) { - if ( queryPlan != null ) { - queryParameters.setQueryPlan( queryPlan ); - } - else if ( hql.equals( getQueryString() ) ) { - queryParameters.setQueryPlan( getQueryPlan() ); - } - } } diff --git a/hibernate-core/src/test/java/org/hibernate/stat/internal/QueryPlanCacheStatisticsTest.java b/hibernate-core/src/test/java/org/hibernate/stat/internal/QueryPlanCacheStatisticsTest.java index 5974b976b0..a0a02b1705 100644 --- a/hibernate-core/src/test/java/org/hibernate/stat/internal/QueryPlanCacheStatisticsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/stat/internal/QueryPlanCacheStatisticsTest.java @@ -6,28 +6,22 @@ */ package org.hibernate.stat.internal; -import java.util.List; import java.util.Map; - import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import javax.persistence.LockModeType; -import javax.persistence.NamedQuery; -import javax.persistence.Tuple; -import javax.persistence.TypedQuery; import org.hibernate.SessionFactory; import org.hibernate.cfg.Environment; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.stat.QueryStatistics; import org.hibernate.stat.Statistics; + import org.hibernate.testing.TestForIssue; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** @@ -45,7 +39,6 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes }; } - @Override protected void addConfigOptions(Map options) { options.put( Environment.GENERATE_STATISTICS, "true" ); } @@ -70,7 +63,6 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes @Test public void test() { - statistics.clear(); assertEquals( 0, statistics.getQueryPlanCacheHitCount() ); assertEquals( 0, statistics.getQueryPlanCacheMissCount() ); @@ -123,165 +115,6 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes } ); } - @Test - @TestForIssue( jiraKey = "HHH-13077" ) - public void testCreateQueryHitCount() { - statistics.clear(); - - doInJPA( this::entityManagerFactory, entityManager -> { - - List employees = entityManager.createQuery( - "select e from Employee e", Employee.class ) - .getResultList(); - - assertEquals( 5, employees.size() ); - - //First time, we get a cache miss, so the query is compiled - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //The hit count should be 0 as we don't need to go to the cache after we already compiled the query - assertEquals( 0, statistics.getQueryPlanCacheHitCount() ); - } ); - - doInJPA( this::entityManagerFactory, entityManager -> { - - List employees = entityManager.createQuery( - "select e from Employee e", Employee.class ) - .getResultList(); - - assertEquals( 5, employees.size() ); - - //The miss count is still 1, as no we got the query plan from the cache - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //And the cache hit count increases. - assertEquals( 1, statistics.getQueryPlanCacheHitCount() ); - } ); - - doInJPA( this::entityManagerFactory, entityManager -> { - - List employees = entityManager.createQuery( - "select e from Employee e", Employee.class ) - .getResultList(); - - assertEquals( 5, employees.size() ); - - //The miss count is still 1, as no we got the query plan from the cache - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //And the cache hit count increases. - assertEquals( 2, statistics.getQueryPlanCacheHitCount() ); - } ); - } - - @Test - @TestForIssue( jiraKey = "HHH-13077" ) - public void testCreateNamedQueryHitCount() { - //This is for the NamedQuery that gets compiled - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - statistics.clear(); - - doInJPA( this::entityManagerFactory, entityManager -> { - - Employee employees = entityManager.createNamedQuery( - "find_employee_by_name", Employee.class ) - .setParameter( "name", "Employee: 1" ) - .getSingleResult(); - - //The miss count is 0 because the plan was compiled when the EMF was built, and we cleared the Statistics - assertEquals( 0, statistics.getQueryPlanCacheMissCount() ); - //The hit count is 1 since we got the plan from the cache - assertEquals( 1, statistics.getQueryPlanCacheHitCount() ); - } ); - - doInJPA( this::entityManagerFactory, entityManager -> { - - Employee employees = entityManager.createNamedQuery( - "find_employee_by_name", Employee.class ) - .setParameter( "name", "Employee: 1" ) - .getSingleResult(); - - //The miss count is still 0 because the plan was compiled when the EMF was built, and we cleared the Statistics - assertEquals( 0, statistics.getQueryPlanCacheMissCount() ); - //The hit count is 2 since we got the plan from the cache twice - assertEquals( 2, statistics.getQueryPlanCacheHitCount() ); - } ); - } - - @Test - @TestForIssue( jiraKey = "HHH-13077" ) - public void testCreateQueryTupleHitCount() { - statistics.clear(); - - doInJPA( this::entityManagerFactory, entityManager -> { - - List employees = entityManager.createQuery( - "select e.id, e.name from Employee e", Tuple.class ) - .getResultList(); - - assertEquals( 5, employees.size() ); - - //First time, we get a cache miss, so the query is compiled - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //The hit count should be 0 as we don't need to go to the cache after we already compiled the query - assertEquals( 0, statistics.getQueryPlanCacheHitCount() ); - } ); - - doInJPA( this::entityManagerFactory, entityManager -> { - - List employees = entityManager.createQuery( - "select e.id, e.name from Employee e", Tuple.class ) - .getResultList(); - - assertEquals( 5, employees.size() ); - - //The miss count is still 1, as no we got the query plan from the cache - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //And the cache hit count increases. - assertEquals( 1, statistics.getQueryPlanCacheHitCount() ); - } ); - - doInJPA( this::entityManagerFactory, entityManager -> { - - List employees = entityManager.createQuery( - "select e.id, e.name from Employee e", Tuple.class ) - .getResultList(); - - assertEquals( 5, employees.size() ); - - //The miss count is still 1, as no we got the query plan from the cache - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //And the cache hit count increases. - assertEquals( 2, statistics.getQueryPlanCacheHitCount() ); - } ); - } - - @Test - @TestForIssue(jiraKey = "HHH-13077") - public void testLockModeHitCount() { - statistics.clear(); - - doInJPA( this::entityManagerFactory, entityManager -> { - TypedQuery typedQuery = entityManager.createQuery( "select e from Employee e", Employee.class ); - - List employees = typedQuery.getResultList(); - - assertEquals( 5, employees.size() ); - - //First time, we get a cache miss, so the query is compiled - assertEquals( 1, statistics.getQueryPlanCacheMissCount() ); - //The hit count should be 0 as we don't need to go to the cache after we already compiled the query - assertEquals( 0, statistics.getQueryPlanCacheHitCount() ); - - typedQuery.setLockMode( LockModeType.READ ); - - //The hit count should still be 0 as setLockMode() shouldn't trigger a cache hit - assertEquals( 0, statistics.getQueryPlanCacheHitCount() ); - - assertNotNull( typedQuery.getLockMode() ); - - //The hit count should still be 0 as getLockMode() shouldn't trigger a cache hit - assertEquals( 0, statistics.getQueryPlanCacheHitCount() ); - } ); - } - private void assertQueryStatistics(String hql, int hitCount) { QueryStatistics queryStatistics = statistics.getQueryStatistics( hql ); @@ -292,10 +125,6 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes } @Entity(name = "Employee") - @NamedQuery( - name = "find_employee_by_name", - query = "select e from Employee e where e.name = :name" - ) public static class Employee { @Id