Revert "HHH-13077 - Optimize query plan call count"
This reverts commit 4f27d5b931
.
This commit is contained in:
parent
4f27d5b931
commit
27118f765c
|
@ -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<T> query = createQuery( queryString );
|
||||
final QueryImplementor<T> 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 <T> QueryImplementor<T> createQuery(NamedQueryDefinition namedQueryDefinition, Class<T> resultType) {
|
||||
final QueryImpl query = createQuery( namedQueryDefinition );
|
||||
final QueryImplementor query = createQuery( namedQueryDefinition );
|
||||
if ( resultType != null ) {
|
||||
resultClassChecking( resultType, query );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -1392,24 +1392,13 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
|
|||
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<R> implements QueryImplementor<R> {
|
|||
: defaultType;
|
||||
}
|
||||
|
||||
protected boolean isSelect() {
|
||||
private boolean isSelect() {
|
||||
return getProducer().getFactory().getQueryPlanCache()
|
||||
.getHQLQueryPlan( getQueryString(), false, Collections.<String, Filter>emptyMap() )
|
||||
.isSelect();
|
||||
|
|
|
@ -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<R> extends AbstractProducedQuery<R> implements Query<R> {
|
||||
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<R> extends AbstractProducedQuery<R> implements Query<R> {
|
|||
return queryString;
|
||||
}
|
||||
|
||||
public HQLQueryPlan getQueryPlan() {
|
||||
return hqlQueryPlan;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNativeQuery() {
|
||||
return false;
|
||||
|
@ -59,14 +50,12 @@ public class QueryImpl<R> extends AbstractProducedQuery<R> implements Query<R> {
|
|||
|
||||
@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<R> extends AbstractProducedQuery<R> implements Query<R> {
|
|||
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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Employee> 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<Employee> 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<Employee> 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<Tuple> 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<Tuple> 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<Tuple> 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<Employee> typedQuery = entityManager.createQuery( "select e from Employee e", Employee.class );
|
||||
|
||||
List<Employee> 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
|
||||
|
|
Loading…
Reference in New Issue