org.hibernate.engine.spi.QueryParameters Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.engine.spi;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.LockOptions;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.util.EntityPrinter;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* @author Gavin King
*/
public final class QueryParameters {
private static final Logger LOG = CoreLogging.logger( QueryParameters.class );
public static final String HQL_VARIABLE_PREFIX = ":";
private Type[] positionalParameterTypes;
private Object[] positionalParameterValues;
private Map namedParameters;
private LockOptions lockOptions;
private RowSelection rowSelection;
private boolean cacheable;
private String cacheRegion;
private String comment;
private List queryHints;
private ScrollMode scrollMode;
private Serializable[] collectionKeys;
private Object optionalObject;
private String optionalEntityName;
private Serializable optionalId;
private boolean isReadOnlyInitialized;
private boolean readOnly;
private boolean callable;
private boolean autodiscovertypes;
private boolean isNaturalKeyLookup;
private boolean passDistinctThrough = true;
private final ResultTransformer resultTransformer; // why is all others non final ?
private String processedSQL;
private Type[] processedPositionalParameterTypes;
private Object[] processedPositionalParameterValues;
public QueryParameters() {
this( ArrayHelper.EMPTY_TYPE_ARRAY, ArrayHelper.EMPTY_OBJECT_ARRAY );
}
public QueryParameters(Type type, Object value) {
this( new Type[] { type }, new Object[] { value } );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Object optionalObject,
final String optionalEntityName,
final Serializable optionalObjectId) {
this( positionalParameterTypes, positionalParameterValues );
this.optionalObject = optionalObject;
this.optionalId = optionalObjectId;
this.optionalEntityName = optionalEntityName;
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues) {
this( positionalParameterTypes, positionalParameterValues, null, null, false, false, false, null, null, null, false, null );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Object[] collectionKeys) {
this( positionalParameterTypes, positionalParameterValues, null, (Serializable[]) collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Serializable[] collectionKeys) {
this( positionalParameterTypes, positionalParameterValues, null, collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Map namedParameters,
final Serializable[] collectionKeys) {
this(
positionalParameterTypes,
positionalParameterValues,
namedParameters,
null,
null,
false,
false,
false,
null,
null,
null,
collectionKeys,
null
);
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
//final boolean forceCacheRefresh,
final String comment,
final List queryHints,
final boolean isLookupByNaturalKey,
final ResultTransformer transformer) {
this(
positionalParameterTypes,
positionalParameterValues,
null,
lockOptions,
rowSelection,
isReadOnlyInitialized,
readOnly,
cacheable,
cacheRegion,
comment,
queryHints,
null,
transformer
);
isNaturalKeyLookup = isLookupByNaturalKey;
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Map namedParameters,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
//final boolean forceCacheRefresh,
final String comment,
final List queryHints,
final Serializable[] collectionKeys,
ResultTransformer transformer) {
this.positionalParameterTypes = positionalParameterTypes;
this.positionalParameterValues = positionalParameterValues;
this.namedParameters = namedParameters;
this.lockOptions = lockOptions;
this.rowSelection = rowSelection;
this.cacheable = cacheable;
this.cacheRegion = cacheRegion;
//this.forceCacheRefresh = forceCacheRefresh;
this.comment = comment;
this.queryHints = queryHints;
this.collectionKeys = collectionKeys;
this.isReadOnlyInitialized = isReadOnlyInitialized;
this.readOnly = readOnly;
this.resultTransformer = transformer;
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] positionalParameterValues,
final Map namedParameters,
final LockOptions lockOptions,
final RowSelection rowSelection,
final boolean isReadOnlyInitialized,
final boolean readOnly,
final boolean cacheable,
final String cacheRegion,
//final boolean forceCacheRefresh,
final String comment,
final List queryHints,
final Serializable[] collectionKeys,
final Object optionalObject,
final String optionalEntityName,
final Serializable optionalId,
final ResultTransformer transformer) {
this(
positionalParameterTypes,
positionalParameterValues,
namedParameters,
lockOptions,
rowSelection,
isReadOnlyInitialized,
readOnly,
cacheable,
cacheRegion,
comment,
queryHints,
collectionKeys,
transformer
);
this.optionalEntityName = optionalEntityName;
this.optionalId = optionalId;
this.optionalObject = optionalObject;
}
public QueryParameters(
QueryParameterBindings queryParameterBindings,
LockOptions lockOptions,
QueryOptions queryOptions,
final Serializable[] collectionKeys,
final Object optionalObject,
final String optionalEntityName,
final Serializable optionalId,
ResultTransformer resultTransformer) {
this(
null,
null,
null,
lockOptions,
new RowSelection(
queryOptions.getFirstRow(),
queryOptions.getMaxRows(),
queryOptions.getTimeout(),
queryOptions.getFetchSize()
),
queryOptions.isReadOnly() != null,
queryOptions.isReadOnly(),
queryOptions.isResultCachingEnabled(),
queryOptions.getResultCacheRegionName(),
queryOptions.getComment(),
queryOptions.getDatabaseHints(),
collectionKeys,
optionalObject,
optionalEntityName,
optionalId,
resultTransformer
);
}
@SuppressWarnings( {"UnusedDeclaration"})
public boolean hasRowSelection() {
return rowSelection != null;
}
public Map getNamedParameters() {
return namedParameters;
}
public Type[] getPositionalParameterTypes() {
return positionalParameterTypes;
}
public Object[] getPositionalParameterValues() {
return positionalParameterValues;
}
public RowSelection getRowSelection() {
return rowSelection;
}
public ResultTransformer getResultTransformer() {
return resultTransformer;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setNamedParameters(Map map) {
namedParameters = map;
}
public void setPositionalParameterTypes(Type[] types) {
positionalParameterTypes = types;
}
public void setPositionalParameterValues(Object[] objects) {
positionalParameterValues = objects;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setRowSelection(RowSelection selection) {
rowSelection = selection;
}
public LockOptions getLockOptions() {
return lockOptions;
}
public void setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
}
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
EntityPrinter print = new EntityPrinter( factory );
if ( positionalParameterValues.length != 0 ) {
LOG.tracev( "Parameters: {0}", print.toString( positionalParameterTypes, positionalParameterValues ) );
}
if ( namedParameters != null ) {
LOG.tracev( "Named parameters: {0}", print.toString( namedParameters ) );
}
}
public boolean isCacheable() {
return cacheable;
}
public void setCacheable(boolean b) {
cacheable = b;
}
public String getCacheRegion() {
return cacheRegion;
}
public void setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
}
public void validateParameters() throws QueryException {
final int types = positionalParameterTypes == null ? 0 : positionalParameterTypes.length;
final int values = positionalParameterValues == null ? 0 : positionalParameterValues.length;
if ( types != values ) {
throw new QueryException(
"Number of positional parameter types:" + types +
" does not match number of positional parameters: " + values
);
}
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public List getQueryHints() {
return queryHints;
}
public void setQueryHints(List queryHints) {
this.queryHints = queryHints;
}
public ScrollMode getScrollMode() {
return scrollMode;
}
public void setScrollMode(ScrollMode scrollMode) {
this.scrollMode = scrollMode;
}
public Serializable[] getCollectionKeys() {
return collectionKeys;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setCollectionKeys(Serializable[] collectionKeys) {
this.collectionKeys = collectionKeys;
}
public String getOptionalEntityName() {
return optionalEntityName;
}
public void setOptionalEntityName(String optionalEntityName) {
this.optionalEntityName = optionalEntityName;
}
public Serializable getOptionalId() {
return optionalId;
}
public void setOptionalId(Serializable optionalId) {
this.optionalId = optionalId;
}
public Object getOptionalObject() {
return optionalObject;
}
public void setOptionalObject(Object optionalObject) {
this.optionalObject = optionalObject;
}
/**
* Has the read-only/modifiable mode been explicitly set?
* @see QueryParameters#setReadOnly(boolean)
* @see QueryParameters#isReadOnly(SharedSessionContractImplementor)
*
* @return true, the read-only/modifiable mode was explicitly set
* false, the read-only/modifiable mode was not explicitly set
*/
public boolean isReadOnlyInitialized() {
return isReadOnlyInitialized;
}
/**
* Should entities and proxies loaded by the Query be put in read-only mode? The
* read-only/modifiable setting must be initialized via QueryParameters#setReadOnly(boolean)
* before calling this method.
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#isReadOnly(SharedSessionContractImplementor)
* @see QueryParameters#setReadOnly(boolean)
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @return true, entities and proxies loaded by the Query will be put in read-only mode
* false, entities and proxies loaded by the Query will be put in modifiable mode
* @throws IllegalStateException if the read-only/modifiable setting has not been
* initialized (i.e., isReadOnlyInitialized() == false).
*/
public boolean isReadOnly() {
if ( !isReadOnlyInitialized() ) {
throw new IllegalStateException( "cannot call isReadOnly() when isReadOnlyInitialized() returns false" );
}
return readOnly;
}
/**
* Should entities and proxies loaded by the Query be put in read-only mode? If the
* read-only/modifiable setting was not initialized (i.e., QueryParameters#isReadOnlyInitialized() == false),
* then the default read-only/modifiable setting for the persistence context is returned instead.
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @param session The originating session
*
* @return {@code true} indicates that entities and proxies loaded by the query will be put in read-only mode;
* {@code false} indicates that entities and proxies loaded by the query will be put in modifiable mode
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#setReadOnly(boolean)
* @see org.hibernate.engine.spi.PersistenceContext#isDefaultReadOnly()
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
*/
public boolean isReadOnly(SharedSessionContractImplementor session) {
return isReadOnlyInitialized
? isReadOnly()
: session.getPersistenceContextInternal().isDefaultReadOnly();
}
/**
* Set the read-only/modifiable mode for entities and proxies loaded by the query.
*
* The read-only/modifiable setting has no impact on entities/proxies returned by the
* query that existed in the session before the query was executed.
*
* @param readOnly if {@code true}, entities and proxies loaded by the query will be put in read-only mode; if
* {@code false}, entities and proxies loaded by the query will be put in modifiable mode
*
* @see QueryParameters#isReadOnlyInitialized()
* @see QueryParameters#isReadOnly(SharedSessionContractImplementor)
* @see QueryParameters#setReadOnly(boolean)
* @see org.hibernate.engine.spi.PersistenceContext#isDefaultReadOnly()
*/
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
this.isReadOnlyInitialized = true;
}
public void setCallable(boolean callable) {
this.callable = callable;
}
public boolean isCallable() {
return callable;
}
public boolean hasAutoDiscoverScalarTypes() {
return autodiscovertypes;
}
/**
* Check if this query should pass the {@code distinct} to the database.
* @return the query passes {@code distinct} to the database
*/
public boolean isPassDistinctThrough() {
return passDistinctThrough;
}
/**
* Set if this query should pass the {@code distinct} to the database.
* @param passDistinctThrough the query passes {@code distinct} to the database
*/
public void setPassDistinctThrough(boolean passDistinctThrough) {
this.passDistinctThrough = passDistinctThrough;
}
public void processFilters(String sql, SharedSessionContractImplementor session) {
processFilters( sql, session.getLoadQueryInfluencers().getEnabledFilters(), session.getFactory() );
}
@SuppressWarnings( {"unchecked"})
public void processFilters(String sql, Map filters, SessionFactoryImplementor factory) {
if ( filters.size() == 0 || !sql.contains( HQL_VARIABLE_PREFIX ) ) {
// HELLA IMPORTANT OPTIMIZATION!!!
processedPositionalParameterValues = getPositionalParameterValues();
processedPositionalParameterTypes = getPositionalParameterTypes();
processedSQL = sql;
}
else {
throw new NotYetImplementedFor6Exception( getClass() );
// final StringTokenizer tokens = new StringTokenizer( sql, SYMBOLS, true );
// StringBuilder result = new StringBuilder();
// List parameters = new ArrayList();
// List parameterTypes = new ArrayList();
// int positionalIndex = 0;
// while ( tokens.hasMoreTokens() ) {
// final String token = tokens.nextToken();
// if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
// final String filterParameterName = token.substring( 1 );
// final String[] parts = LoadQueryInfluencers.parseFilterParameterName( filterParameterName );
// final FilterImpl filter = (FilterImpl) filters.get( parts[0] );
// final Object value = filter.getParameter( parts[1] );
// final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
// if ( value != null && Collection.class.isAssignableFrom( value.getClass() ) ) {
// Iterator itr = ( (Collection) value ).iterator();
// while ( itr.hasNext() ) {
// final Object elementValue = itr.next();
// result.append( '?' );
// parameters.add( elementValue );
// parameterTypes.add( type );
// if ( itr.hasNext() ) {
// result.append( ", " );
// }
// }
// }
// else {
// result.append( '?' );
// parameters.add( value );
// parameterTypes.add( type );
// }
// }
// else {
// result.append( token );
// if ( "?".equals( token ) && positionalIndex < getPositionalParameterValues().length ) {
// final Type type = getPositionalParameterTypes()[positionalIndex];
// if ( type.isComponentType() ) {
// // should process tokens till reaching the number of "?" corresponding to the
// // numberOfParametersCoveredBy of the compositeType
// int paramIndex = 1;
// final int numberOfParametersCoveredBy = getNumberOfParametersCoveredBy( ((ComponentType) type).getSubtypes() );
// while ( paramIndex < numberOfParametersCoveredBy ) {
// final String nextToken = tokens.nextToken();
// if ( "?".equals( nextToken ) ) {
// paramIndex++;
// }
// result.append( nextToken );
// }
// }
// parameters.add( getPositionalParameterValues()[positionalIndex] );
// parameterTypes.add( type );
// positionalIndex++;
// }
// }
// }
// processedPositionalParameterValues = parameters.toArray();
// processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[parameterTypes.size()] );
// processedSQL = result.toString();
}
}
private int getNumberOfParametersCoveredBy(Type[] subtypes) {
int numberOfParameters = 0;
for ( Type type : subtypes ) {
if ( type.isComponentType() ) {
numberOfParameters = numberOfParameters + getNumberOfParametersCoveredBy( ((ComponentType) type).getSubtypes() );
}
else {
numberOfParameters++;
}
}
return numberOfParameters;
}
public String getFilteredSQL() {
return processedSQL;
}
public Object[] getFilteredPositionalParameterValues() {
return processedPositionalParameterValues;
}
public Type[] getFilteredPositionalParameterTypes() {
return processedPositionalParameterTypes;
}
public boolean isNaturalKeyLookup() {
return isNaturalKeyLookup;
}
@SuppressWarnings( {"UnusedDeclaration"})
public void setNaturalKeyLookup(boolean isNaturalKeyLookup) {
this.isNaturalKeyLookup = isNaturalKeyLookup;
}
public void setAutoDiscoverScalarTypes(boolean autodiscovertypes) {
this.autodiscovertypes = autodiscovertypes;
}
public QueryParameters createCopyUsing(RowSelection selection) {
QueryParameters copy = new QueryParameters(
this.positionalParameterTypes,
this.positionalParameterValues,
this.namedParameters,
this.lockOptions,
selection,
this.isReadOnlyInitialized,
this.readOnly,
this.cacheable,
this.cacheRegion,
this.comment,
this.queryHints,
this.collectionKeys,
this.optionalObject,
this.optionalEntityName,
this.optionalId,
this.resultTransformer
);
copy.processedSQL = this.processedSQL;
copy.processedPositionalParameterTypes = this.processedPositionalParameterTypes;
copy.processedPositionalParameterValues = this.processedPositionalParameterValues;
copy.passDistinctThrough = this.passDistinctThrough;
return copy;
}
public void bindDynamicParameter(Type paramType, Object paramValue) {
if(processedPositionalParameterTypes != null) {
int length = processedPositionalParameterTypes.length;
Type[] types = new Type[length + 1];
Object[] values = new Object[length + 1];
for ( int i = 0; i < length; i++ ) {
types[i] = processedPositionalParameterTypes[i];
values[i] = processedPositionalParameterValues[i];
}
types[length] = paramType;
values[length] = paramValue;
processedPositionalParameterTypes = types;
processedPositionalParameterValues = values;
}
}
}