From 954a8416abaa0c12bf2bcda55ceabf39cf109809 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Mon, 19 May 2014 14:23:13 +0200 Subject: [PATCH] HHH-9190 Introducing QueryPlanFactory service contract in order to make creation of native query plans customizable (cherry picked from commit ac06799a551724b4ea654f13da1ac0f9064b6eb1) --- .../query/spi/DefaultQueryPlanFactory.java | 51 +++++++++++++++++ .../engine/query/spi/NativeSQLQueryPlan.java | 31 ++++------- .../engine/query/spi/QueryPlanCache.java | 5 +- .../engine/query/spi/QueryPlanFactory.java | 55 +++++++++++++++++++ .../query/spi/QueryPlanFactoryInitiator.java | 55 +++++++++++++++++++ ...andardSessionFactoryServiceInitiators.java | 2 + 6 files changed, 178 insertions(+), 21 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/query/spi/DefaultQueryPlanFactory.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactory.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactoryInitiator.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/DefaultQueryPlanFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/DefaultQueryPlanFactory.java new file mode 100644 index 0000000000..ca847e28d1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/DefaultQueryPlanFactory.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.query.spi; + +import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.loader.custom.CustomQuery; +import org.hibernate.loader.custom.sql.SQLCustomQuery; + +/** + * Default query plan factory used by Hibernate ORM. Creates query plans for SQL + * queries. + * + * @author Gunnar Morling + * + */ +public class DefaultQueryPlanFactory implements QueryPlanFactory { + + @Override + public NativeSQLQueryPlan createNativeQueryPlan(NativeSQLQuerySpecification nativeQuerySpecification, SessionFactoryImplementor sessionFactory) { + CustomQuery customQuery = new SQLCustomQuery( + nativeQuerySpecification.getQueryString(), + nativeQuerySpecification.getQueryReturns(), + nativeQuerySpecification.getQuerySpaces(), + sessionFactory + ); + + return new NativeSQLQueryPlan( nativeQuerySpecification.getQueryString(), customQuery ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/NativeSQLQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/NativeSQLQueryPlan.java index ae13e45808..27d331d434 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/NativeSQLQueryPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/NativeSQLQueryPlan.java @@ -33,16 +33,14 @@ import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.QueryException; import org.hibernate.action.internal.BulkOperationCleanupAction; -import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification; import org.hibernate.engine.spi.QueryParameters; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.TypedValue; import org.hibernate.event.spi.EventSource; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.loader.custom.sql.SQLCustomQuery; +import org.hibernate.loader.custom.CustomQuery; import org.hibernate.type.Type; /** @@ -54,31 +52,24 @@ public class NativeSQLQueryPlan implements Serializable { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( NativeSQLQueryPlan.class ); private final String sourceQuery; - private final SQLCustomQuery customQuery; + private final CustomQuery customQuery; /** - * Constructs a NativeSQLQueryPlan - * - * @param specification The query spec - * @param factory The SessionFactory - */ - public NativeSQLQueryPlan( - NativeSQLQuerySpecification specification, - SessionFactoryImplementor factory) { - this.sourceQuery = specification.getQueryString(); - this.customQuery = new SQLCustomQuery( - specification.getQueryString(), - specification.getQueryReturns(), - specification.getQuerySpaces(), - factory - ); + * Constructs a NativeSQLQueryPlan. + * + * @param sourceQuery The original native query to create a plan for + * @param customQuery The query executed via this plan + */ + public NativeSQLQueryPlan(String sourceQuery, CustomQuery customQuery) { + this.sourceQuery = sourceQuery; + this.customQuery = customQuery; } public String getSourceQuery() { return sourceQuery; } - public SQLCustomQuery getCustomQuery() { + public CustomQuery getCustomQuery() { return customQuery; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java index a4079fd965..f87d1b3da4 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java @@ -222,7 +222,10 @@ public class QueryPlanCache implements Serializable { NativeSQLQueryPlan value = (NativeSQLQueryPlan) queryPlanCache.get( spec ); if ( value == null ) { LOG.tracev( "Unable to locate native-sql query plan in cache; generating ({0})", spec.getQueryString() ); - value = new NativeSQLQueryPlan( spec, factory); + value = factory.getServiceRegistry() + .getService(QueryPlanFactory.class ) + .createNativeQueryPlan( spec, factory ); + queryPlanCache.putIfAbsent( spec, value ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactory.java new file mode 100644 index 0000000000..13f776e37a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactory.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.query.spi; + +import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.service.Service; +import org.hibernate.service.spi.SessionFactoryServiceInitiator; + +/** + * Contract for factories of query plans. + *

+ * The default implementation creates query plans for SQL queries, but + * integrators can plug in another factory by registering a custom + * {@link SessionFactoryServiceInitiator} for this service contract. + * + * @author Gunnar Morling + * + */ +public interface QueryPlanFactory extends Service { + + /** + * Creates a new query plan for the specified native query. + * + * @param nativeQuerySpecification + * Describes the query to create a plan for + * @param sessionFactory + * The current session factory + * @return A query plan for the specified native query. + */ + NativeSQLQueryPlan createNativeQueryPlan( + NativeSQLQuerySpecification nativeQuerySpecification, + SessionFactoryImplementor sessionFactory); +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactoryInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactoryInitiator.java new file mode 100644 index 0000000000..5f6d05d60f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanFactoryInitiator.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.engine.query.spi; + +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.SessionFactoryServiceInitiator; + +/** + * Initiates the default {@link QueryPlanFactory}. + * + * @author Gunnar Morling + */ +public class QueryPlanFactoryInitiator implements SessionFactoryServiceInitiator { + + public static final QueryPlanFactoryInitiator INSTANCE = new QueryPlanFactoryInitiator(); + + @Override + public QueryPlanFactory initiateService(SessionFactoryImplementor sessionFactory, Configuration configuration, ServiceRegistryImplementor registry) { + return new DefaultQueryPlanFactory(); + } + + @Override + public QueryPlanFactory initiateService(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata, ServiceRegistryImplementor registry) { + return new DefaultQueryPlanFactory(); + } + + @Override + public Class getServiceInitiated() { + return QueryPlanFactory.class; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/StandardSessionFactoryServiceInitiators.java b/hibernate-core/src/main/java/org/hibernate/service/internal/StandardSessionFactoryServiceInitiators.java index 620673840e..81891872cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/StandardSessionFactoryServiceInitiators.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/StandardSessionFactoryServiceInitiators.java @@ -28,6 +28,7 @@ import java.util.Collections; import java.util.List; import org.hibernate.engine.query.spi.ParameterMetadataRecognizerInitiator; +import org.hibernate.engine.query.spi.QueryPlanFactoryInitiator; import org.hibernate.engine.spi.CacheInitiator; import org.hibernate.event.service.internal.EventListenerServiceInitiator; import org.hibernate.service.spi.SessionFactoryServiceInitiator; @@ -49,6 +50,7 @@ public class StandardSessionFactoryServiceInitiators { serviceInitiators.add( StatisticsInitiator.INSTANCE ); serviceInitiators.add( CacheInitiator.INSTANCE ); serviceInitiators.add( ParameterMetadataRecognizerInitiator.INSTANCE ); + serviceInitiators.add( QueryPlanFactoryInitiator.INSTANCE ); return Collections.unmodifiableList( serviceInitiators ); }