diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterMetadataRecognizer.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterMetadataRecognizer.java
new file mode 100644
index 0000000000..cf0b12f161
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterMetadataRecognizer.java
@@ -0,0 +1,52 @@
+/*
+ * 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.service.Service;
+import org.hibernate.service.spi.SessionFactoryServiceInitiator;
+
+/**
+ * Service contract for extracting {@link ParameterMetadata} from given native
+ * queries.
+ *
+ * The default implementation extracts parameter meta-data from native SQL
+ * queries, but integrators can plug-in alternative recognizer implementations
+ * by contributing a custom {@link SessionFactoryServiceInitiator} for this
+ * service contract.
+ *
+ * @author Gunnar Morling
+ */
+public interface ParameterMetadataRecognizer extends Service {
+
+ /**
+ * Returns a meta-data object with information about the named and ordinal
+ * parameters contained in the given native query.
+ *
+ * @param nativeQuery
+ * the native query to analyze.
+ * @return a meta-data object describing the parameters of the given query.
+ * Must not be {@code null}.
+ */
+ ParameterMetadata getParameterMetadata(String nativeQuery);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterMetadataRecognizerInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterMetadataRecognizerInitiator.java
new file mode 100644
index 0000000000..5bbf819b3f
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterMetadataRecognizerInitiator.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 ParameterMetadataRecognizer}.
+ *
+ * @author Gunnar Morling
+ */
+public class ParameterMetadataRecognizerInitiator implements SessionFactoryServiceInitiator {
+
+ public static final ParameterMetadataRecognizerInitiator INSTANCE = new ParameterMetadataRecognizerInitiator();
+
+ @Override
+ public ParameterMetadataRecognizer initiateService(SessionFactoryImplementor sessionFactory, Configuration configuration, ServiceRegistryImplementor registry) {
+ return new SQLParameterMetadataRecognizer();
+ }
+
+ @Override
+ public ParameterMetadataRecognizer initiateService(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata, ServiceRegistryImplementor registry) {
+ return new SQLParameterMetadataRecognizer();
+ }
+
+ @Override
+ public Class getServiceInitiated() {
+ return ParameterMetadataRecognizer.class;
+ }
+}
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 19b4e16845..a4079fd965 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
@@ -135,38 +135,14 @@ public class QueryPlanCache implements Serializable {
public ParameterMetadata getSQLParameterMetadata(final String query) {
ParameterMetadata value = parameterMetadataCache.get( query );
if ( value == null ) {
- value = buildParameterMetadata( query );
+ value = factory.getServiceRegistry()
+ .getService( ParameterMetadataRecognizer.class )
+ .getParameterMetadata( query );
+
parameterMetadataCache.putIfAbsent( query, value );
}
return value;
}
-
- private ParameterMetadata buildParameterMetadata(String query){
- final ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( query );
-
- final int size = recognizer.getOrdinalParameterLocationList().size();
- final OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[ size ];
- for ( int i = 0; i < size; i++ ) {
- final Integer position = recognizer.getOrdinalParameterLocationList().get( i );
- ordinalDescriptors[i] = new OrdinalParameterDescriptor( i, null, position );
- }
-
- final Map namedParamDescriptorMap = new HashMap();
- final Map map = recognizer.getNamedParameterDescriptionMap();
- for ( final String name : map.keySet() ) {
- final ParamLocationRecognizer.NamedParameterDescription description = map.get( name );
- namedParamDescriptorMap.put(
- name,
- new NamedParameterDescriptor(
- name,
- null,
- description.buildPositionsArray(),
- description.isJpaStyle()
- )
- );
- }
- return new ParameterMetadata( ordinalDescriptors, namedParamDescriptorMap );
- }
/**
* Get the query plan for the given HQL query, creating it and caching it if not already cached
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/SQLParameterMetadataRecognizer.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/SQLParameterMetadataRecognizer.java
new file mode 100644
index 0000000000..0cfd32f14e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/SQLParameterMetadataRecognizer.java
@@ -0,0 +1,67 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ParameterMetadataRecognizer} which retrieves parameter meta-data
+ * from native SQL queries.
+ *
+ * @author Gunnar Morling
+ *
+ */
+public class SQLParameterMetadataRecognizer implements ParameterMetadataRecognizer {
+
+ @Override
+ public ParameterMetadata getParameterMetadata(String nativeQuery) {
+ final ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( nativeQuery );
+
+ final int size = recognizer.getOrdinalParameterLocationList().size();
+ final OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[ size ];
+ for ( int i = 0; i < size; i++ ) {
+ final Integer position = recognizer.getOrdinalParameterLocationList().get( i );
+ ordinalDescriptors[i] = new OrdinalParameterDescriptor( i, null, position );
+ }
+
+ final Map namedParamDescriptorMap = new HashMap();
+ final Map map = recognizer.getNamedParameterDescriptionMap();
+
+ for ( final String name : map.keySet() ) {
+ final ParamLocationRecognizer.NamedParameterDescription description = map.get( name );
+ namedParamDescriptorMap.put(
+ name,
+ new NamedParameterDescriptor(
+ name,
+ null,
+ description.buildPositionsArray(),
+ description.isJpaStyle()
+ )
+ );
+ }
+
+ return new ParameterMetadata( ordinalDescriptors, namedParamDescriptorMap );
+ }
+}
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 c60a94eda6..620673840e 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
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.hibernate.engine.query.spi.ParameterMetadataRecognizerInitiator;
import org.hibernate.engine.spi.CacheInitiator;
import org.hibernate.event.service.internal.EventListenerServiceInitiator;
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
@@ -47,6 +48,7 @@ public class StandardSessionFactoryServiceInitiators {
serviceInitiators.add( EventListenerServiceInitiator.INSTANCE );
serviceInitiators.add( StatisticsInitiator.INSTANCE );
serviceInitiators.add( CacheInitiator.INSTANCE );
+ serviceInitiators.add( ParameterMetadataRecognizerInitiator.INSTANCE );
return Collections.unmodifiableList( serviceInitiators );
}