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 ); }