HHH-9190 Introducing ParameterMetadataRecognizer contract in order to make retrieval fo parameter meta-data for native queries customizable

This commit is contained in:
Gunnar Morling 2014-05-19 14:33:15 +02:00 committed by Steve Ebersole
parent 07bc5ce877
commit ccdf6df3d6
5 changed files with 180 additions and 28 deletions

View File

@ -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.
* <p>
* 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);
}

View File

@ -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<ParameterMetadataRecognizer> {
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<ParameterMetadataRecognizer> getServiceInitiated() {
return ParameterMetadataRecognizer.class;
}
}

View File

@ -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<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
final Map<String, ParamLocationRecognizer.NamedParameterDescription> 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

View File

@ -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<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
final Map<String, ParamLocationRecognizer.NamedParameterDescription> 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 );
}
}

View File

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