All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.engine.spi.QueryParameters Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * 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 .
 */
package org.hibernate.engine.spi;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.hibernate.HibernateException;
import org.hibernate.LockOptions;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.hql.internal.classic.ParserHelper;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.FilterImpl;
import org.hibernate.internal.util.EntityPrinter;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.query.internal.QueryParameterBindingsImpl;
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 );

	/**
	 * Symbols used to split SQL string into tokens in {@link #processFilters(String, Map, SessionFactoryImplementor)}.
	 */
	private static final String SYMBOLS = ParserHelper.HQL_SEPARATORS.replace( "'", "" );

	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;

	private HQLQueryPlan queryPlan;

	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 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,
			RowSelection selection,
			final boolean isReadOnlyInitialized,
			boolean readOnly,
			boolean cacheable,
			String cacheRegion,
			String comment,
			List dbHints,
			final Serializable[] collectionKeys,
			final Object optionalObject,
			final String optionalEntityName,
			final Serializable optionalId,
			ResultTransformer resultTransformer) {
		this(
				queryParameterBindings.collectPositionalBindTypes(),
				queryParameterBindings.collectPositionalBindValues(),
				queryParameterBindings.collectNamedParameterBindings(),
				lockOptions,
				selection,
				isReadOnlyInitialized,
				readOnly,
				cacheable,
				cacheRegion,
				comment,
				dbHints,
				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( ParserHelper.HQL_VARIABLE_PREFIX ) ) { // HELLA IMPORTANT OPTIMIZATION!!! processedPositionalParameterValues = getPositionalParameterValues(); processedPositionalParameterTypes = getPositionalParameterTypes(); processedSQL = sql; } else { 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 HQLQueryPlan getQueryPlan() { return queryPlan; } public void setQueryPlan(HQLQueryPlan queryPlan) { this.queryPlan = queryPlan; } 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; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy