
org.hibernate.query.sql.internal.NativeQueryImpl Maven / Gradle / Ivy
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.query.sql.internal;
import java.io.Serializable;
import java.time.Instant;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import jakarta.persistence.PessimisticLockScope;
import jakarta.persistence.Timeout;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jpa.spi.NativeQueryConstructorTransformer;
import org.hibernate.jpa.spi.NativeQueryListTransformer;
import org.hibernate.jpa.spi.NativeQueryMapTransformer;
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.ScrollMode;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.util.MathHelper;
import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.query.KeyedPage;
import org.hibernate.query.KeyedResultList;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.PathException;
import org.hibernate.query.Query;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer;
import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.internal.QueryOptionsImpl;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.internal.Builders;
import org.hibernate.query.results.ResultBuilder;
import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.results.internal.ResultSetMappingImpl;
import org.hibernate.query.results.internal.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderBasicStandard;
import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderEntityCalculated;
import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderEntityStandard;
import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderInstantiation;
import org.hibernate.query.results.internal.implicit.ImplicitModelPartResultBuilderEntity;
import org.hibernate.query.results.internal.implicit.ImplicitResultClassBuilder;
import org.hibernate.query.spi.AbstractQuery;
import org.hibernate.query.spi.DomainQueryExecutionContext;
import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
import org.hibernate.query.sql.spi.NativeSelectQueryDefinition;
import org.hibernate.query.sql.spi.NativeSelectQueryPlan;
import org.hibernate.query.sql.spi.NonSelectInterpretationsKey;
import org.hibernate.query.sql.spi.ParameterInterpretation;
import org.hibernate.query.sql.spi.ParameterOccurrence;
import org.hibernate.query.sql.spi.SelectInterpretationsKey;
import org.hibernate.sql.exec.internal.CallbackImpl;
import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.spi.SingleResultConsumer;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeReference;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.Parameter;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.TemporalType;
import jakarta.persistence.Tuple;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.metamodel.SingularAttribute;
import jakarta.persistence.metamodel.Type;
import static java.lang.Character.isWhitespace;
import static java.util.Collections.addAll;
import static org.hibernate.internal.util.ReflectHelper.isClass;
import static org.hibernate.internal.util.StringHelper.unqualify;
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
import static org.hibernate.internal.util.collections.CollectionHelper.makeCopy;
import static org.hibernate.jpa.HibernateHints.HINT_NATIVE_LOCK_MODE;
import static org.hibernate.query.results.internal.Builders.resultClassBuilder;
import static org.hibernate.query.results.ResultSetMapping.resolveResultSetMapping;
import static org.hibernate.query.sqm.internal.SqmUtil.isResultTypeAlwaysAllowed;
/**
* @author Steve Ebersole
*/
public class NativeQueryImpl
extends AbstractQuery
implements NativeQueryImplementor, DomainQueryExecutionContext, ResultSetMappingResolutionContext {
private static final CoreMessageLogger log = CoreLogging.messageLogger( NativeQueryImpl.class );
private final String sqlString;
private final String originalSqlString;
private final ParameterMetadataImplementor parameterMetadata;
private final List parameterOccurrences;
private final QueryParameterBindings parameterBindings;
private final Class resultType;
private final ResultSetMapping resultSetMapping;
private final boolean resultMappingSuppliedToCtor;
private final HashMap entityMappingTypeByTableAlias = new HashMap<>();
private final QueryOptionsImpl queryOptions = new QueryOptionsImpl();
private Boolean startsWithSelect;
private Set querySpaces;
private Callback callback;
/**
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
* Used by Hibernate Reactive.
*/
@SuppressWarnings("unused")
public NativeQueryImpl(NamedNativeQueryMemento> memento, SharedSessionContractImplementor session) {
this(
memento,
() -> buildResultSetMapping( getResultSetMappingName( memento ), false, session ),
(resultSetMapping, querySpaceConsumer, context ) -> {
if ( memento.getResultMappingName() != null ) {
final NamedResultSetMappingMemento resultSetMappingMemento =
getNamedObjectRepository( session )
.getResultSetMappingMemento( memento.getResultMappingName() );
if ( resultSetMappingMemento != null ) {
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
}
}
if ( memento.getResultType() != null ) {
resultSetMapping.addResultBuilder( resultClassBuilder( memento.getResultType(), context ) );
return true;
}
else {
return false;
}
},
null,
session
);
}
/**
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
*/
public NativeQueryImpl(
NamedNativeQueryMemento> memento,
Class resultJavaType,
SharedSessionContractImplementor session) {
this(
memento,
() -> {
final String mappingIdentifier = resultJavaType != null ? resultJavaType.getName() : null;
return buildResultSetMapping( mappingIdentifier, false, session );
},
(resultSetMapping, querySpaceConsumer, context) -> {
if ( memento.getResultMappingName() != null ) {
final NamedResultSetMappingMemento resultSetMappingMemento =
getNamedObjectRepository( session )
.getResultSetMappingMemento( memento.getResultMappingName() );
if ( resultSetMappingMemento != null ) {
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
}
}
if ( memento.getResultType() != null ) {
resultSetMapping.addResultBuilder( resultClassBuilder( memento.getResultType(), context ) );
return true;
}
else {
return false;
}
},
resultJavaType,
session
);
}
/**
* Constructs a NativeQueryImpl given a sql query defined in the mappings.
*/
public NativeQueryImpl(
NamedNativeQueryMemento> memento,
String resultSetMappingName,
SharedSessionContractImplementor session) {
this(
memento,
() -> buildResultSetMapping( resultSetMappingName, false, session ),
(resultSetMapping, querySpaceConsumer, context) -> {
final NamedResultSetMappingMemento mappingMemento =
getNamedObjectRepository( session )
.getResultSetMappingMemento( resultSetMappingName );
assert mappingMemento != null;
mappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
return true;
},
null,
session
);
}
private NativeQueryImpl(
NamedNativeQueryMemento> memento,
Supplier resultSetMappingCreator,
ResultSetMappingHandler resultSetMappingHandler,
@Nullable Class resultClass,
SharedSessionContractImplementor session) {
super( session );
originalSqlString = memento.getOriginalSqlString();
querySpaces = new HashSet<>();
final ParameterInterpretation parameterInterpretation =
resolveParameterInterpretation( originalSqlString, session );
sqlString = parameterInterpretation.getAdjustedSqlString();
parameterMetadata = parameterInterpretation.toParameterMetadata( session );
parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
parameterBindings = parameterMetadata.createBindings( session.getFactory() );
resultSetMapping = resultSetMappingCreator.get();
resultMappingSuppliedToCtor =
resultSetMappingHandler.resolveResultSetMapping( resultSetMapping, querySpaces::add, this );
resultType = resultClass;
handleExplicitResultSetMapping();
applyOptions( memento );
}
public NativeQueryImpl(
String sql,
NamedResultSetMappingMemento resultSetMappingMemento,
Class resultClass,
SharedSessionContractImplementor session) {
super( session );
originalSqlString = sql;
querySpaces = new HashSet<>();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sql, session );
sqlString = parameterInterpretation.getAdjustedSqlString();
parameterMetadata = parameterInterpretation.toParameterMetadata( session );
parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
parameterBindings = parameterMetadata.createBindings( session.getFactory() );
resultSetMapping = buildResultSetMapping( resultSetMappingMemento.getName(), false, session );
resultSetMappingMemento.resolve( resultSetMapping, this::addSynchronizedQuerySpace, this );
resultMappingSuppliedToCtor = true;
resultType = resultClass;
handleExplicitResultSetMapping();
}
public NativeQueryImpl(String sql, @Nullable Class resultClass, SharedSessionContractImplementor session) {
super( session );
originalSqlString = sql;
querySpaces = new HashSet<>();
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sql, session );
sqlString = parameterInterpretation.getAdjustedSqlString();
parameterMetadata = parameterInterpretation.toParameterMetadata( session );
parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences();
parameterBindings = parameterMetadata.createBindings( session.getFactory() );
resultSetMapping = resolveResultSetMapping( sql, true, session.getFactory() );
resultMappingSuppliedToCtor = false;
resultType = resultClass;
handleImplicitResultSetMapping( session );
}
private void handleImplicitResultSetMapping(SharedSessionContractImplementor session) {
if ( resultType != null && !session.getFactory().getMappingMetamodel().isEntityClass( resultType ) ) {
setTupleTransformerForResultType( resultType );
}
}
private void handleExplicitResultSetMapping() {
if ( resultType != null ) {
if ( isResultTypeAlwaysAllowed( resultType ) ) {
setTupleTransformerForResultType( resultType );
}
else {
checkResultType( resultType );
}
}
}
private void checkResultType(Class resultType) {
switch ( resultSetMapping.getNumberOfResultBuilders() ) {
case 0:
throw new IllegalArgumentException( "Named query exists, but did not specify a resultClass" );
case 1:
final Class> actualResultJavaType =
resultSetMapping.getResultBuilders().get( 0 ).getJavaType();
if ( actualResultJavaType != null && !resultType.isAssignableFrom( actualResultJavaType ) ) {
throw buildIncompatibleException( resultType, actualResultJavaType );
}
break;
default:
throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
}
}
protected void setTupleTransformerForResultType(Class resultClass) {
final TupleTransformer> tupleTransformer = determineTupleTransformerForResultType( resultClass );
if ( tupleTransformer != null ) {
setTupleTransformer( tupleTransformer );
}
}
/**
* If the result type of the query is {@link Tuple}, {@link Map}, {@link List},
* or any record or class type with an appropriate constructor which is NOT a
* registered basic type, then we attempt to repackage the result tuple as an
* instance of the result type using an appropriate {@link TupleTransformer}.
*
* @param resultClass The requested result type of the query
* @return A {@link TupleTransformer} responsible for repackaging the result type
*/
protected @Nullable TupleTransformer> determineTupleTransformerForResultType(Class> resultClass) {
if ( Tuple.class.equals( resultClass ) ) {
return NativeQueryTupleTransformer.INSTANCE;
}
else if ( Map.class.equals( resultClass ) ) {
return NativeQueryMapTransformer.INSTANCE;
}
else if ( List.class.equals( resultClass ) ) {
return NativeQueryListTransformer.INSTANCE;
}
else if ( resultClass != Object.class && resultClass != Object[].class ) {
// TODO: this is extremely fragile and probably a bug
if ( isClass( resultClass ) && !hasJavaTypeDescriptor( resultClass ) ) {
// not a basic type, so something we can attempt
// to instantiate to repackage the results
return new NativeQueryConstructorTransformer<>( resultClass );
}
}
return null;
}
private boolean hasJavaTypeDescriptor(Class resultClass) {
final JavaType> descriptor = getTypeConfiguration().getJavaTypeRegistry().findDescriptor( resultClass );
return descriptor != null && descriptor.getClass() != UnknownBasicJavaType.class;
}
private static NamedObjectRepository getNamedObjectRepository(SharedSessionContractImplementor session) {
return session.getFactory().getQueryEngine().getNamedObjectRepository();
}
private static QueryInterpretationCache getInterpretationCache(SharedSessionContractImplementor session) {
return session.getFactory().getQueryEngine().getInterpretationCache();
}
private static String getResultSetMappingName(NamedNativeQueryMemento> memento) {
if ( memento.getResultMappingName() != null ) {
return memento.getResultMappingName();
}
else if ( memento.getResultType() != null ) {
return memento.getResultType().getName();
}
else {
return memento.getSqlString();
}
}
@FunctionalInterface
private interface ResultSetMappingHandler {
boolean resolveResultSetMapping(
ResultSetMapping resultSetMapping,
Consumer querySpaceConsumer,
ResultSetMappingResolutionContext context);
}
private static ResultSetMapping buildResultSetMapping(
String registeredName,
boolean isDynamic,
SharedSessionContractImplementor session) {
return resolveResultSetMapping( registeredName, isDynamic, session.getFactory() );
}
public List getParameterOccurrences() {
return parameterOccurrences;
}
private ParameterInterpretation resolveParameterInterpretation(
String sqlString, SharedSessionContractImplementor session) {
return getInterpretationCache( session )
.resolveNativeQueryParameters( sqlString,
s -> parameterInterpretation( sqlString, session ) );
}
private static ParameterInterpretationImpl parameterInterpretation(
String sqlString, SharedSessionContractImplementor session) {
final ParameterRecognizerImpl parameterRecognizer = new ParameterRecognizerImpl();
session.getFactory().getServiceRegistry()
.requireService( NativeQueryInterpreter.class )
.recognizeParameters( sqlString, parameterRecognizer );
return new ParameterInterpretationImpl( parameterRecognizer );
}
protected void applyOptions(NamedNativeQueryMemento> memento) {
super.applyOptions( memento );
if ( memento.getMaxResults() != null ) {
setMaxResults( memento.getMaxResults() );
}
if ( memento.getFirstResult() != null ) {
setFirstResult( memento.getFirstResult() );
}
final Set mementoQuerySpaces = memento.getQuerySpaces();
if ( mementoQuerySpaces != null ) {
querySpaces = makeCopy( mementoQuerySpaces );
}
// todo (6.0) : query returns
}
private IllegalArgumentException buildIncompatibleException(Class> resultClass, Class> actualResultClass) {
final String resultClassName = resultClass.getName();
final String actualResultClassName = actualResultClass.getName();
if ( resultClassName.equals( actualResultClassName ) ) {
return new IllegalArgumentException(
"Type specified for TypedQuery [" + resultClassName +
"] is incompatible with the query return type of the same name." +
" Both classes have the same name but are different as they have been loaded respectively by Classloaders " +
resultClass.getClassLoader().toString() + ", " + actualResultClass.getClassLoader().toString() +
". This suggests a classloader bug in the Runtime executing Hibernate ORM, or in the integration code."
);
}
else {
return new IllegalArgumentException(
"Type specified for TypedQuery [" + resultClassName +
"] is incompatible with query return type [" + actualResultClass + "]"
);
}
}
@Override
public String getQueryString() {
return sqlString;
}
@Override
public ParameterMetadataImplementor getParameterMetadata() {
return parameterMetadata;
}
@Override
public MutableQueryOptions getQueryOptions() {
return queryOptions;
}
@Override
public Callback getCallback() {
if ( callback == null ) {
callback = new CallbackImpl();
}
return callback;
}
@Override
public boolean hasCallbackActions() {
return callback != null && callback.hasAfterLoadActions();
}
@Override
public QueryParameterBindings getQueryParameterBindings() {
return parameterBindings;
}
@Override
public QueryParameterBindings getParameterBindings() {
return getQueryParameterBindings();
}
@Override
public Class getResultType() {
return resultType;
}
@Override
public NamedNativeQueryMemento toMemento(String name) {
return new NamedNativeQueryMementoImpl<>(
name,
resultType != null ? resultType : extractResultClass( resultSetMapping ),
sqlString,
originalSqlString,
resultSetMapping.getMappingIdentifier(),
querySpaces,
isCacheable(),
getCacheRegion(),
getCacheMode(),
getQueryOptions().getFlushMode(),
isReadOnly(),
getTimeout(),
getFetchSize(),
getComment(),
getQueryOptions().getLimit().getFirstRow(),
getQueryOptions().getLimit().getMaxRows(),
getHints()
);
}
private Class extractResultClass(ResultSetMapping resultSetMapping) {
final List resultBuilders = resultSetMapping.getResultBuilders();
if ( resultBuilders.size() == 1 ) {
final ResultBuilder resultBuilder = resultBuilders.get( 0 );
if ( resultBuilder instanceof ImplicitResultClassBuilder
|| resultBuilder instanceof ImplicitModelPartResultBuilderEntity
|| resultBuilder instanceof DynamicResultBuilderEntityCalculated ) {
return (Class) resultBuilder.getJavaType();
}
}
return null;
}
@Override
public LockModeType getLockMode() {
// the JPA spec requires IllegalStateException here, even
// though it's logically an UnsupportedOperationException
throw new IllegalStateException( "Illegal attempt to get lock mode on a native-query" );
}
@Override @Deprecated
public NativeQueryImplementor setLockOptions(LockOptions lockOptions) {
super.setLockOptions( lockOptions );
return this;
}
@Override
public NativeQueryImplementor setHibernateLockMode(LockMode lockMode) {
super.setHibernateLockMode( lockMode );
return this;
}
@Override
public NativeQueryImplementor setTimeout(Timeout timeout) {
super.setTimeout( timeout );
return this;
}
@Override
public NativeQueryImplementor setLockScope(PessimisticLockScope lockScope) {
super.setLockScope( lockScope );
return this;
}
@Override
public NativeQueryImplementor setLockMode(String alias, LockMode lockMode) {
// throw IllegalStateException here for consistency with JPA
throw new IllegalStateException( "Illegal attempt to set lock mode for a native query" );
}
@Override
public NativeQueryImplementor setLockMode(LockModeType lockModeType) {
// the JPA spec requires IllegalStateException here, even
// though it's logically an UnsupportedOperationException
throw new IllegalStateException( "Illegal attempt to set lock mode for a native query" );
}
@Override
protected void applyGraph(String graphString, GraphSemantic graphSemantic) {
throw new HibernateException( "A native SQL query cannot use EntityGraphs" );
}
@Override
protected void applyGraph(RootGraphImplementor> entityGraph, GraphSemantic graphSemantic) {
throw new HibernateException( "A native SQL query cannot use EntityGraphs" );
}
@Override
public Query applyGraph(@SuppressWarnings("rawtypes") RootGraph graph, GraphSemantic semantic) {
throw new HibernateException( "A native SQL query cannot use EntityGraphs" );
}
@Override
protected void applyEntityGraphHint(String hintName, Object value) {
super.applyEntityGraphHint( hintName, value );
}
@Override
public NativeQueryImplementor setTupleTransformer(TupleTransformer transformer) {
super.setTupleTransformer( transformer );
//TODO: this is bad, we should really return a new instance
return (NativeQueryImplementor) this;
}
@Override
public NativeQueryImplementor setResultListTransformer(ResultListTransformer transformer) {
super.setResultListTransformer( transformer );
return this;
}
@Override
public Boolean isSelectQuery() {
if ( resultMappingSuppliedToCtor
|| resultSetMapping.getNumberOfResultBuilders() > 0
|| isReadOnly()
// as a last resort, see if the SQL starts with "select"
|| startsWithSelect() ) {
return true;
}
else {
return null;
}
}
private boolean startsWithSelect() {
if ( startsWithSelect == null ) {
startsWithSelect = sqlString.toLowerCase( Locale.ROOT ).startsWith( "select " );
}
return startsWithSelect;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execution
@Override
protected void prepareForExecution() {
final Collection spaces = getSynchronizedQuerySpaces();
if ( spaces == null || spaces.isEmpty() ) {
// We need to flush. The query itself is not required to execute in a
// transaction; if there is no transaction, the flush would throw a
// TransactionRequiredException which would potentially break existing
// apps, so we only do the flush if a transaction is in progress.
if ( shouldFlush() ) {
getSession().flush();
}
// Reset the callback before every execution
callback = null;
}
// Otherwise, the application specified query spaces via the Hibernate
// SynchronizeableQuery and so the query will already perform a partial
// flush according to the defined query spaces - no need for a full flush.
}
private boolean shouldFlush() {
if ( getSession().isTransactionInProgress() ) {
final FlushMode flushMode = getQueryOptions().getFlushMode();
return switch ( flushMode == null ? getSession().getHibernateFlushMode() : flushMode ) {
// The JPA spec requires that we auto-flush before native queries
case AUTO -> getSessionFactory().getSessionFactoryOptions().isJpaBootstrap();
case ALWAYS -> true;
default -> false;
};
}
else {
return false;
}
}
@Override
protected List doList() {
return resolveSelectQueryPlan().performList( this );
}
@Override
public long getResultCount() {
final DelegatingDomainQueryExecutionContext context = new DelegatingDomainQueryExecutionContext(this) {
@Override
public QueryOptions getQueryOptions() {
return QueryOptions.NONE;
}
};
return createCountQueryPlan().executeQuery( context, SingleResultConsumer.instance() );
}
@Override
public KeyedResultList getKeyedResultList(KeyedPage page) {
throw new UnsupportedOperationException("native queries do not support key-based pagination");
}
protected SelectQueryPlan resolveSelectQueryPlan() {
final ResultSetMapping mapping;
if ( resultType != null && resultSetMapping.isDynamic() && resultSetMapping.getNumberOfResultBuilders() == 0 ) {
mapping = ResultSetMapping.resolveResultSetMapping( originalSqlString, true, getSessionFactory() );
if ( getSessionFactory().getMappingMetamodel().isEntityClass( resultType ) ) {
mapping.addResultBuilder(
Builders.entityCalculated( unqualify( resultType.getName() ), resultType.getName(),
LockMode.READ, getSessionFactory() ) );
}
else if ( !isResultTypeAlwaysAllowed( resultType )
&& (!isClass( resultType ) || hasJavaTypeDescriptor( resultType )) ) {
mapping.addResultBuilder( Builders.resultClassBuilder( resultType, getSessionFactory().getMappingMetamodel() ) );
}
}
else {
mapping = resultSetMapping;
}
return isCacheableQuery()
? getInterpretationCache()
.resolveSelectQueryPlan( selectInterpretationsKey( mapping ), () -> createQueryPlan( mapping ) )
: createQueryPlan( mapping );
}
private NativeSelectQueryPlan createQueryPlan(ResultSetMapping resultSetMapping) {
final NativeSelectQueryDefinition queryDefinition = new NativeSelectQueryDefinition<>() {
final String sqlString = expandParameterLists();
@Override
public String getSqlString() {
return sqlString;
}
@Override
public boolean isCallable() {
return false;
}
@Override
public List getQueryParameterOccurrences() {
return parameterOccurrences;
}
@Override
public ResultSetMapping getResultSetMapping() {
return resultSetMapping;
}
@Override
public Set getAffectedTableNames() {
return querySpaces;
}
};
return getNativeQueryInterpreter().createQueryPlan( queryDefinition, getSessionFactory() );
}
/*
* Used by Hibernate Reactive
*/
protected NativeSelectQueryPlan createCountQueryPlan() {
final NativeSelectQueryDefinition queryDefinition = new NativeSelectQueryDefinition<>() {
final BasicType longType = getTypeConfiguration().getBasicTypeForJavaType(Long.class);
final String sqlString = expandParameterLists();
@Override
public String getSqlString() {
return "select count(*) from (" + sqlString + ") a_";
}
@Override
public boolean isCallable() {
return false;
}
@Override
public List getQueryParameterOccurrences() {
return parameterOccurrences;
}
@Override
public ResultSetMapping getResultSetMapping() {
final ResultSetMappingImpl mapping = new ResultSetMappingImpl( "", true );
mapping.addResultBuilder( new DynamicResultBuilderBasicStandard( 1, longType ) );
return mapping;
}
@Override
public Set getAffectedTableNames() {
return querySpaces;
}
};
return getNativeQueryInterpreter().createQueryPlan( queryDefinition, getSessionFactory() );
}
private NativeQueryInterpreter getNativeQueryInterpreter() {
return getSessionFactory().getQueryEngine().getNativeQueryInterpreter();
}
protected String expandParameterLists() {
if ( parameterOccurrences == null || parameterOccurrences.isEmpty() ) {
return sqlString;
}
// HHH-1123
// Some DBs limit number of IN expressions. For now, warn...
final SessionFactoryImplementor factory = getSessionFactory();
final Dialect dialect = factory.getJdbcServices().getDialect();
final boolean paddingEnabled = factory.getSessionFactoryOptions().inClauseParameterPaddingEnabled();
final int inExprLimit = dialect.getInExpressionCountLimit();
StringBuilder sql = null;
// Handle parameter lists
int offset = 0;
for ( ParameterOccurrence occurrence : parameterOccurrences ) {
final QueryParameterImplementor> queryParameter = occurrence.parameter();
final QueryParameterBinding> binding = parameterBindings.getBinding( queryParameter );
if ( binding.isMultiValued() ) {
final int bindValueCount = binding.getBindValues().size();
logTooManyExpressions( inExprLimit, bindValueCount, dialect, queryParameter );
final int sourcePosition = occurrence.sourcePosition();
if ( sourcePosition >= 0 ) {
// check if placeholder is already immediately enclosed in parentheses
// (ignoring whitespace)
final boolean isEnclosedInParens = isEnclosedInParens( sourcePosition );
// short-circuit for performance when only 1 value and the
// placeholder is already enclosed in parentheses...
if ( bindValueCount != 1 || !isEnclosedInParens ) {
if ( sql == null ) {
sql = new StringBuilder( sqlString.length() + 20 );
sql.append( sqlString );
}
final int bindValueMaxCount =
determineBindValueMaxCount( paddingEnabled, inExprLimit, bindValueCount );
final String expansionListAsString =
expandList( bindValueMaxCount, isEnclosedInParens );
final int start = sourcePosition + offset;
final int end = start + 1;
sql.replace( start, end, expansionListAsString );
offset += expansionListAsString.length() - 1;
}
}
}
}
return sql == null ? sqlString : sql.toString();
}
private static void logTooManyExpressions(
int inExprLimit, int bindValueCount,
Dialect dialect, QueryParameterImplementor> queryParameter) {
if ( inExprLimit > 0 && bindValueCount > inExprLimit ) {
log.tooManyInExpressions(
dialect.getClass().getName(),
inExprLimit,
queryParameter.getName() == null
? queryParameter.getPosition().toString()
: queryParameter.getName(),
bindValueCount
);
}
}
private static String expandList(int bindValueMaxCount, boolean isEnclosedInParens) {
// HHH-8901
if ( bindValueMaxCount == 0 ) {
return isEnclosedInParens ? "null" : "(null)";
}
else {
// Shift 1 bit instead of multiplication by 2
final char[] chars;
if ( isEnclosedInParens ) {
chars = new char[(bindValueMaxCount << 1) - 1];
chars[0] = '?';
for ( int i = 1; i < bindValueMaxCount; i++ ) {
final int index = i << 1;
chars[index - 1] = ',';
chars[index] = '?';
}
}
else {
chars = new char[(bindValueMaxCount << 1) + 1];
chars[0] = '(';
chars[1] = '?';
for ( int i = 1; i < bindValueMaxCount; i++ ) {
final int index = i << 1;
chars[index] = ',';
chars[index + 1] = '?';
}
chars[chars.length - 1] = ')';
}
return new String( chars );
}
}
private boolean isEnclosedInParens(int sourcePosition) {
boolean isEnclosedInParens = true;
for ( int i = sourcePosition - 1; i >= 0; i-- ) {
final char ch = sqlString.charAt( i );
if ( !isWhitespace( ch ) ) {
isEnclosedInParens = ch == '(';
break;
}
}
if ( isEnclosedInParens ) {
for ( int i = sourcePosition + 1; i < sqlString.length(); i++ ) {
final char ch = sqlString.charAt( i );
if ( !isWhitespace( ch ) ) {
isEnclosedInParens = ch == ')';
break;
}
}
}
return isEnclosedInParens;
}
public static int determineBindValueMaxCount(boolean paddingEnabled, int inExprLimit, int bindValueCount) {
int bindValueMaxCount = bindValueCount;
final boolean inClauseParameterPaddingEnabled = paddingEnabled && bindValueCount > 2;
if ( inClauseParameterPaddingEnabled ) {
int bindValuePaddingCount = MathHelper.ceilingPowerOfTwo( bindValueCount );
if ( inExprLimit > 0 && bindValuePaddingCount > inExprLimit ) {
bindValuePaddingCount = inExprLimit;
}
if ( bindValueCount < bindValuePaddingCount ) {
bindValueMaxCount = bindValuePaddingCount;
}
}
return bindValueMaxCount;
}
private SelectInterpretationsKey selectInterpretationsKey(ResultSetMapping resultSetMapping) {
return new SelectInterpretationsKey(
getQueryString(),
resultSetMapping,
getSynchronizedQuerySpaces(),
getQueryOptions().getTupleTransformer(),
getQueryOptions().getResultListTransformer()
);
}
private boolean isCacheableQuery() {
// todo (6.0): unless we move the limit rendering from DeferredResultSetAccess to NativeSelectQueryPlanImpl
// we don't need to consider the limit here at all because that is applied on demand.
// It certainly is better for performance to include the limit early, but then we might trash the cache
// if ( hasLimit( query.getQueryOptions().getLimit() ) ) {
// return false;
// }
// For now, don't cache plans that have parameter lists
return !parameterBindings.hasAnyMultiValuedBindings();
}
@Override
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
return resolveSelectQueryPlan().performScroll( scrollMode, this );
}
protected int doExecuteUpdate() {
return resolveNonSelectQueryPlan().executeUpdate( this );
}
private BasicTypeRegistry getBasicTypeRegistry() {
return getTypeConfiguration().getBasicTypeRegistry();
}
private QueryInterpretationCache getInterpretationCache() {
return getInterpretationCache( getSession() );
}
private NonSelectQueryPlan resolveNonSelectQueryPlan() {
NonSelectQueryPlan queryPlan = null;
final QueryInterpretationCache.Key cacheKey = generateNonSelectInterpretationsKey();
if ( cacheKey != null ) {
queryPlan = getInterpretationCache().getNonSelectQueryPlan( cacheKey );
}
if ( queryPlan == null ) {
final String sqlString = expandParameterLists();
queryPlan = new NativeNonSelectQueryPlanImpl( sqlString, querySpaces, parameterOccurrences );
if ( cacheKey != null ) {
getInterpretationCache().cacheNonSelectQueryPlan( cacheKey, queryPlan );
}
}
return queryPlan;
}
protected NonSelectInterpretationsKey generateNonSelectInterpretationsKey() {
// todo (6.0) - should this account for query spaces in determining "cacheable"?
return isCacheableQuery()
? new NonSelectInterpretationsKey( getQueryString(), getSynchronizedQuerySpaces() )
: null;
}
@Override
public void addResultTypeClass(Class> resultClass) {
assert resultSetMapping.getNumberOfResultBuilders() == 0;
registerBuilder( Builders.resultClassBuilder( resultClass, getSessionFactory().getMappingMetamodel() ) );
}
@Override
public NativeQueryImplementor addScalar(String columnAlias) {
return registerBuilder( Builders.scalar( columnAlias ) );
}
public NativeQueryImplementor addScalar(int position, Class> type) {
return registerBuilder( Builders.scalar( position, getBasicTypeRegistry().getRegisteredType( type ) ) );
}
protected NativeQueryImplementor registerBuilder(ResultBuilder builder) {
resultSetMapping.addResultBuilder( builder );
return this;
}
@Override
public NativeQuery addScalar(String columnAlias, @SuppressWarnings("rawtypes") BasicTypeReference type) {
return registerBuilder( Builders.scalar( columnAlias,
getBasicTypeRegistry().resolve( (BasicTypeReference>) type ) ) );
}
@Override
public NativeQueryImplementor addScalar(String columnAlias, @SuppressWarnings("rawtypes") BasicDomainType type) {
return registerBuilder( Builders.scalar( columnAlias, (BasicType>) type ) );
}
@Override
public NativeQueryImplementor addScalar(String columnAlias, @SuppressWarnings("rawtypes") Class javaType) {
return registerBuilder( Builders.scalar( columnAlias, javaType, getSessionFactory() ) );
}
@Override
public NativeQueryImplementor addScalar(
String columnAlias,
Class jdbcJavaType,
AttributeConverter, C> converter) {
return registerBuilder( Builders.converted( columnAlias, jdbcJavaType, converter, getSessionFactory() ) );
}
@Override
public NativeQueryImplementor addScalar(
String columnAlias,
Class domainJavaType,
Class jdbcJavaType,
AttributeConverter converter) {
return registerBuilder( Builders.converted( columnAlias, domainJavaType, jdbcJavaType, converter, getSessionFactory() ) );
}
@Override
public NativeQueryImplementor addScalar(
String columnAlias,
Class relationalJavaType,
Class extends AttributeConverter, C>> converter) {
return registerBuilder( Builders.converted( columnAlias, relationalJavaType, converter, getSessionFactory() ) );
}
@Override
public NativeQueryImplementor addScalar(
String columnAlias,
Class domainJavaType,
Class jdbcJavaType,
Class extends AttributeConverter> converterJavaType) {
return registerBuilder( Builders.converted( columnAlias, domainJavaType, jdbcJavaType, converterJavaType, getSessionFactory() ) );
}
@Override
public InstantiationResultNode addInstantiation(Class targetJavaType) {
final DynamicResultBuilderInstantiation builder =
Builders.instantiation( targetJavaType, getSessionFactory() );
registerBuilder( builder );
return builder;
}
@Override
public NativeQueryImplementor addAttributeResult(
String columnAlias,
@SuppressWarnings("rawtypes") Class entityJavaType,
String attributePath) {
return addAttributeResult( columnAlias, entityJavaType.getName(), attributePath );
}
@Override
public NativeQueryImplementor addAttributeResult(
String columnAlias,
String entityName,
String attributePath) {
registerBuilder( Builders.attributeResult( columnAlias, entityName, attributePath, getSessionFactory() ) );
return this;
}
@Override
public NativeQueryImplementor addAttributeResult(
String columnAlias,
@SuppressWarnings("rawtypes") SingularAttribute attribute) {
registerBuilder( Builders.attributeResult( columnAlias, attribute, getSessionFactory() ) );
return this;
}
@Override
public DynamicResultBuilderEntityStandard addRoot(String tableAlias, String entityName) {
final DynamicResultBuilderEntityStandard resultBuilder =
Builders.entity( tableAlias, entityName, getSessionFactory() );
resultSetMapping.addResultBuilder( resultBuilder );
entityMappingTypeByTableAlias.put( tableAlias, resultBuilder.getEntityMapping() );
return resultBuilder;
}
@Override
public DynamicResultBuilderEntityStandard addRoot(String tableAlias, @SuppressWarnings("rawtypes") Class entityType) {
return addRoot( tableAlias, entityType.getName() );
}
@Override
public NativeQueryImplementor addEntity(String entityName) {
return addEntity( unqualify( entityName ), entityName );
}
@Override
public NativeQueryImplementor addEntity(String tableAlias, String entityName) {
final DynamicResultBuilderEntityCalculated builder =
Builders.entityCalculated( tableAlias, entityName, getSessionFactory() );
entityMappingTypeByTableAlias.put( tableAlias, builder.getEntityMapping() );
registerBuilder( builder );
return this;
}
@Override
public NativeQueryImplementor addEntity(String tableAlias, String entityName, LockMode lockMode) {
final DynamicResultBuilderEntityCalculated builder =
Builders.entityCalculated( tableAlias, entityName, lockMode, getSessionFactory() );
entityMappingTypeByTableAlias.put( tableAlias, builder.getEntityMapping() );
registerBuilder( builder );
return this;
}
@Override
public NativeQueryImplementor addEntity(@SuppressWarnings("rawtypes") Class entityType) {
return addEntity( entityType.getName() );
}
@Override
public NativeQueryImplementor addEntity(Class entityType, LockMode lockMode) {
return addEntity( unqualify( entityType.getName() ), entityType.getName(), lockMode);
}
@Override
public NativeQueryImplementor addEntity(String tableAlias, @SuppressWarnings("rawtypes") Class entityClass) {
return addEntity( tableAlias, entityClass.getName() );
}
@Override
public NativeQueryImplementor addEntity(String tableAlias, @SuppressWarnings("rawtypes") Class entityClass, LockMode lockMode) {
return addEntity( tableAlias, entityClass.getName(), lockMode );
}
@Override
public FetchReturn addFetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
final ModelPart subPart = entityMappingTypeByTableAlias.get( ownerTableAlias ).findSubPart( joinPropertyName );
addEntityMappingType( tableAlias, subPart );
final DynamicFetchBuilderLegacy fetchBuilder = Builders.fetch( tableAlias, ownerTableAlias, (Fetchable) subPart );
resultSetMapping.addLegacyFetchBuilder( fetchBuilder );
return fetchBuilder;
}
private void addEntityMappingType(String tableAlias, ModelPart part) {
if ( part instanceof PluralAttributeMapping pluralAttributeMapping ) {
final MappingType partMappingType = pluralAttributeMapping.getElementDescriptor().getPartMappingType();
if ( partMappingType instanceof EntityMappingType entityMappingType ) {
entityMappingTypeByTableAlias.put( tableAlias, entityMappingType );
}
}
else if ( part instanceof EntityAssociationMapping entityAssociationMapping ) {
entityMappingTypeByTableAlias.put( tableAlias, entityAssociationMapping.asEntityMappingType() );
}
else if ( part instanceof EmbeddedAttributeMapping ) {
throw new UnsupportedOperationException();
}
}
@Override
public NativeQueryImplementor addJoin(String tableAlias, String path) {
createFetchJoin( tableAlias, path );
return this;
}
private FetchReturn createFetchJoin(String tableAlias, String path) {
final int loc = path.indexOf( '.' );
if ( loc < 0 ) {
throw new PathException( "Not a property path '" + path + "'" );
}
final String ownerTableAlias = path.substring( 0, loc );
final String joinedPropertyName = path.substring( loc + 1 );
return addFetch( tableAlias, ownerTableAlias, joinedPropertyName );
}
@Override
public NativeQueryImplementor addJoin(String tableAlias, String ownerTableAlias, String joinPropertyName) {
addFetch( tableAlias, ownerTableAlias, joinPropertyName );
return this;
}
@Override
public NativeQueryImplementor addJoin(String tableAlias, String path, LockMode lockMode) {
createFetchJoin( tableAlias, path ).setLockMode( lockMode );
return this;
}
@Override
public Collection getSynchronizedQuerySpaces() {
return querySpaces;
}
@Override
public NativeQueryImplementor addSynchronizedQuerySpace(String querySpace) {
addQuerySpaces( querySpace );
return this;
}
protected void addQuerySpaces(String... spaces) {
if ( spaces != null ) {
if ( querySpaces == null ) {
querySpaces = new HashSet<>();
}
addAll( querySpaces, spaces );
}
}
protected void addQuerySpaces(Serializable... spaces) {
if ( spaces != null ) {
if ( querySpaces == null ) {
querySpaces = new HashSet<>();
}
addAll( querySpaces, (String[]) spaces );
}
}
@Override
public NativeQueryImplementor addSynchronizedEntityName(String entityName) {
addQuerySpaces( getMappingMetamodel().getEntityDescriptor( entityName ).getQuerySpaces() );
return this;
}
@Override
public NativeQueryImplementor addSynchronizedEntityClass(@SuppressWarnings("rawtypes") Class entityClass) {
addQuerySpaces( getMappingMetamodel().getEntityDescriptor( entityClass ).getQuerySpaces() );
return this;
}
@Override
public NativeQueryImplementor setHibernateFlushMode(FlushMode flushMode) {
super.setHibernateFlushMode( flushMode );
return this;
}
@Override
public NativeQueryImplementor setQueryFlushMode(QueryFlushMode queryFlushMode) {
super.setQueryFlushMode(queryFlushMode);
return this;
}
@Override
public NativeQueryImplementor setFlushMode(FlushModeType flushModeType) {
super.setFlushMode( flushModeType );
return this;
}
@Override
public NativeQueryImplementor setCacheMode(CacheMode cacheMode) {
super.setCacheMode( cacheMode );
return this;
}
@Override
public NativeQueryImplementor setCacheRetrieveMode(CacheRetrieveMode cacheRetrieveMode) {
super.setCacheRetrieveMode( cacheRetrieveMode );
return this;
}
@Override
public NativeQueryImplementor setCacheStoreMode(CacheStoreMode cacheStoreMode) {
super.setCacheStoreMode( cacheStoreMode );
return this;
}
@Override
public TypedQuery setTimeout(Integer timeout) {
if ( timeout == null ) {
timeout = -1;
}
super.setTimeout( (int) timeout );
return this;
}
@Override
public NativeQueryImplementor setCacheable(boolean cacheable) {
super.setCacheable( cacheable );
return this;
}
@Override
public NativeQueryImplementor setCacheRegion(String cacheRegion) {
super.setCacheRegion( cacheRegion );
return this;
}
@Override
public NativeQueryImplementor setQueryPlanCacheable(boolean queryPlanCacheable) {
super.setQueryPlanCacheable( queryPlanCacheable );
return this;
}
@Override
public NativeQueryImplementor setTimeout(int timeout) {
super.setTimeout( timeout );
return this;
}
@Override
public NativeQueryImplementor setFetchSize(int fetchSize) {
super.setFetchSize( fetchSize );
return this;
}
@Override
public NativeQueryImplementor setReadOnly(boolean readOnly) {
super.setReadOnly( readOnly );
return this;
}
@Override
public T unwrap(Class type) {
if ( type.isInstance( this ) ) {
return type.cast( this );
}
if ( type.isInstance( parameterMetadata ) ) {
return type.cast( parameterMetadata );
}
if ( type.isInstance( parameterBindings ) ) {
return type.cast( parameterBindings );
}
if ( type.isInstance( getQueryOptions() ) ) {
return type.cast( getQueryOptions() );
}
if ( type.isInstance( getQueryOptions().getAppliedGraph() ) ) {
return type.cast( getQueryOptions().getAppliedGraph() );
}
if ( type.isInstance( getSession() ) ) {
return type.cast( getSession() );
}
throw new PersistenceException( "Unrecognized unwrap type [" + type.getName() + "]" );
}
@Override
public NativeQueryImplementor setComment(String comment) {
super.setComment( comment );
return this;
}
@Override
public NativeQueryImplementor addQueryHint(String hint) {
super.addQueryHint( hint );
return this;
}
@Override
protected void collectHints(Map hints) {
super.collectHints( hints );
putIfNotNull( hints, HINT_NATIVE_LOCK_MODE, getLockOptions().getLockMode() );
}
protected void applySynchronizeSpacesHint(Object value) {
applySynchronizeSpace( value );
}
protected void applySynchronizeSpace(Object value) {
if ( value instanceof String string ) {
addSynchronizedQuerySpace( string );
}
else if ( value instanceof Class> clazz ) {
addSynchronizedEntityClass( clazz );
}
else if ( value instanceof Object[] array ) {
for ( Object element : array ) {
applySynchronizeSpace( element );
}
}
else if ( value instanceof Iterable> iterable ) {
for ( Object element : iterable ) {
applySynchronizeSpace( element );
}
}
}
@Override
public NativeQueryImplementor setParameter(String name, Object value) {
super.setParameter( name, value );
return this;
}
@Override
public NativeQueryImplementor setParameter(String name, P value, Class javaTypeClass) {
super.setParameter( name, value, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameter(String name, P value, Type type) {
super.setParameter( name, value, type );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(String name, Calendar value, TemporalType temporalType) {
super.setParameter( name, value, temporalType );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(String name, Instant value, TemporalType temporalType) {
super.setParameter( name, value, temporalType );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(String name, Date value, TemporalType temporalType) {
super.setParameter( name, value, temporalType );
return this;
}
@Override
public NativeQueryImplementor setParameter(int position, Object value) {
super.setParameter( position, value );
return this;
}
@Override
public NativeQueryImplementor setParameter(int position, P value, Class javaTypeClass) {
super.setParameter( position, value, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameter(int position, P value, Type type) {
super.setParameter( position, value, type );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(int position, Instant value, TemporalType temporalType) {
super.setParameter( position, value, temporalType );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(int position, Calendar value, TemporalType temporalType) {
super.setParameter( position, value, temporalType );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(int position, Date value, TemporalType temporalType) {
super.setParameter( position, value, temporalType );
return this;
}
@Override
public NativeQueryImplementor setParameter(QueryParameter parameter, P value) {
super.setParameter( parameter, value );
return this;
}
@Override
public
NativeQueryImplementor setParameter(QueryParameter parameter, P value, Class
javaTypeClass) {
super.setParameter( parameter, value, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameter(QueryParameter parameter, P value, Type
type) {
super.setParameter( parameter, value, type );
return this;
}
@Override
public
NativeQueryImplementor setParameter(Parameter parameter, P value) {
super.setParameter( parameter, value );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(Parameter param, Calendar value, TemporalType temporalType) {
super.setParameter( param, value, temporalType );
return this;
}
@Override @Deprecated
public NativeQueryImplementor setParameter(Parameter param, Date value, TemporalType temporalType) {
super.setParameter( param, value, temporalType );
return this;
}
@Override
public NativeQueryImplementor setParameterList(String name, @SuppressWarnings("rawtypes") Collection values) {
super.setParameterList( name, values );
return this;
}
@Override
public NativeQueryImplementor setParameterList(String name, Collection extends P> values, Class javaTypeClass) {
super.setParameterList( name, values, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(String name, Collection extends P> values, Type type) {
super.setParameterList( name, values, type );
return this;
}
@Override
public NativeQueryImplementor setParameterList(String name, Object[] values) {
super.setParameterList( name, values );
return this;
}
@Override
public NativeQueryImplementor setParameterList(String name, P[] values, Class javaTypeClass) {
super.setParameterList( name, values, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(String name, P[] values, Type type) {
super.setParameterList( name, values, type );
return this;
}
@Override
public NativeQueryImplementor setParameterList(int position, @SuppressWarnings("rawtypes") Collection values) {
super.setParameterList( position, values );
return this;
}
@Override
public NativeQueryImplementor setParameterList(int position, Collection extends P> values, Class javaTypeClass) {
super.setParameterList( position, values, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(int position, Collection extends P> values, Type type) {
super.setParameterList( position, values, type );
return this;
}
@Override
public NativeQueryImplementor setParameterList(int position, Object[] values) {
super.setParameterList( position, values );
return this;
}
@Override
public NativeQueryImplementor setParameterList(int position, P[] values, Class javaTypeClass) {
super.setParameterList( position, values, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(int position, P[] values, Type type) {
super.setParameterList( position, values, type );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(QueryParameter parameter, Collection extends P> values) {
super.setParameterList( parameter, values );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(QueryParameter parameter, Collection extends P> values, Class
javaTypeClass) {
super.setParameterList( parameter, values, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(QueryParameter parameter, Collection extends P> values, Type
type) {
super.setParameterList( parameter, values, type );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(QueryParameter parameter, P[] values) {
super.setParameterList( parameter, values );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(QueryParameter parameter, P[] values, Class
javaTypeClass) {
super.setParameterList( parameter, values, javaTypeClass );
return this;
}
@Override
public
NativeQueryImplementor setParameterList(QueryParameter parameter, P[] values, Type
type) {
super.setParameterList( parameter, values, type );
return this;
}
@Override
public NativeQueryImplementor setProperties(@SuppressWarnings("rawtypes") Map map) {
super.setProperties( map );
return this;
}
@Override
public NativeQueryImplementor setProperties(Object bean) {
super.setProperties( bean );
return this;
}
@Override @Deprecated @SuppressWarnings("deprecation")
public NativeQueryImplementor setResultTransformer(ResultTransformer transformer) {
return setTupleTransformer( transformer ).setResultListTransformer( transformer );
}
@Override
public NativeQueryImplementor setMaxResults(int maxResults) {
super.setMaxResults( maxResults );
return this;
}
@Override
public NativeQueryImplementor setFirstResult(int startPosition) {
super.setFirstResult( startPosition );
return this;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hints
@Override
public NativeQueryImplementor setHint(String hintName, Object value) {
super.setHint( hintName, value );
return this;
}
private static class ParameterInterpretationImpl implements ParameterInterpretation {
private final String sqlString;
private final List parameterList;
private final Map> positionalParameters;
private final Map> namedParameters;
public ParameterInterpretationImpl(ParameterRecognizerImpl parameterRecognizer) {
this.sqlString = parameterRecognizer.getAdjustedSqlString();
this.parameterList = parameterRecognizer.getParameterList();
this.positionalParameters = parameterRecognizer.getPositionalQueryParameters();
this.namedParameters = parameterRecognizer.getNamedQueryParameters();
}
@Override
public List getOrderedParameterOccurrences() {
return parameterList;
}
@Override
public ParameterMetadataImplementor toParameterMetadata(SharedSessionContractImplementor session1) {
return isEmpty( positionalParameters ) && isEmpty( namedParameters )
? ParameterMetadataImpl.EMPTY
: new ParameterMetadataImpl( positionalParameters, namedParameters );
}
@Override
public String getAdjustedSqlString() {
return sqlString;
}
@Override
public String toString() {
final StringBuilder buffer =
new StringBuilder( "ParameterInterpretationImpl (" )
.append( sqlString )
.append( ") : {" );
final String lineSeparator = System.lineSeparator();
if ( isNotEmpty( parameterList ) ) {
for ( int i = 0, size = parameterList.size(); i < size; i++ ) {
buffer.append( lineSeparator ).append( " ," );
}
buffer.setLength( buffer.length() - 1 );
}
return buffer.append( lineSeparator ).append( "}" ).toString();
}
}
}