FileDocCategorySizeDatePackage
QueryLoader.javaAPI DocHibernate 3.2.517619Tue Jan 30 07:29:40 GMT 2007org.hibernate.loader.hql

QueryLoader

public class QueryLoader extends org.hibernate.loader.BasicLoader
A delegate that implements the Loader part of QueryTranslator.
author
josh

Fields Summary
private org.hibernate.hql.ast.QueryTranslatorImpl
queryTranslator
The query translator that is delegating to this object.
private org.hibernate.persister.entity.Queryable[]
entityPersisters
private String[]
entityAliases
private String[]
sqlAliases
private String[]
sqlAliasSuffixes
private boolean[]
includeInSelect
private String[]
collectionSuffixes
private boolean
hasScalars
private String[]
scalarColumnNames
private org.hibernate.type.Type[]
queryReturnTypes
private final Map
sqlAliasByEntityAlias
private org.hibernate.type.EntityType[]
ownerAssociationTypes
private int[]
owners
private boolean[]
entityEagerPropertyFetches
private int[]
collectionOwners
private org.hibernate.persister.collection.QueryableCollection[]
collectionPersisters
private int
selectLength
private org.hibernate.transform.ResultTransformer
selectNewTransformer
private String[]
queryReturnAliases
private org.hibernate.LockMode[]
defaultLockModes
Constructors Summary
public QueryLoader(org.hibernate.hql.ast.QueryTranslatorImpl queryTranslator, org.hibernate.engine.SessionFactoryImplementor factory, org.hibernate.hql.ast.tree.SelectClause selectClause)
Creates a new Loader implementation.

param
queryTranslator The query translator that is the delegator.
param
factory The factory from which this loader is being created.
param
selectClause The AST representing the select clause for loading.



	                                   	 
	 
			  
	          
	           
		super( factory );
		this.queryTranslator = queryTranslator;
		initialize( selectClause );
		postInstantiate();
	
Methods Summary
protected java.lang.StringapplyLocks(java.lang.String sql, java.util.Map lockModes, org.hibernate.dialect.Dialect dialect)

		if ( lockModes == null || lockModes.size() == 0 ) {
			return sql;
		}

		// can't cache this stuff either (per-invocation)
		// we are given a map of user-alias -> lock mode
		// create a new map of sql-alias -> lock mode
		final Map aliasedLockModes = new HashMap();
		final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
		final Iterator iter = lockModes.entrySet().iterator();
		while ( iter.hasNext() ) {
			Map.Entry me = ( Map.Entry ) iter.next();
			final String userAlias = ( String ) me.getKey();
			final String drivingSqlAlias = ( String ) sqlAliasByEntityAlias.get( userAlias );
			if ( drivingSqlAlias == null ) {
				throw new IllegalArgumentException( "could not locate alias to apply lock mode : " + userAlias );
			}
			// at this point we have (drivingSqlAlias) the SQL alias of the driving table
			// corresponding to the given user alias.  However, the driving table is not
			// (necessarily) the table against which we want to apply locks.  Mainly,
			// the exception case here is joined-subclass hierarchies where we instead
			// want to apply the lock against the root table (for all other strategies,
			// it just happens that driving and root are the same).
			final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST();
			final Lockable drivingPersister = ( Lockable ) select.getFromClause().getFromElement( userAlias ).getQueryable();
			final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
			aliasedLockModes.put( sqlAlias, me.getValue() );
			if ( keyColumnNames != null ) {
				keyColumnNames.put( sqlAlias, drivingPersister.getRootTableIdentifierColumnNames() );
			}
		}
		return dialect.applyLocksToSql( sql, aliasedLockModes, keyColumnNames );
	
private intbindFilterParameterValues(java.sql.PreparedStatement st, org.hibernate.engine.QueryParameters queryParameters, int position, org.hibernate.engine.SessionImplementor session)

		// todo : better to handle dynamic filters through implicit DynamicFilterParameterSpecification
		// see the discussion there in DynamicFilterParameterSpecification's javadocs as to why
		// it is currently not done that way.
		int filteredParamCount = queryParameters.getFilteredPositionalParameterTypes() == null
				? 0
				: queryParameters.getFilteredPositionalParameterTypes().length;
		int nonfilteredParamCount = queryParameters.getPositionalParameterTypes() == null
				? 0
				: queryParameters.getPositionalParameterTypes().length;
		int filterParamCount = filteredParamCount - nonfilteredParamCount;
		for ( int i = 0; i < filterParamCount; i++ ) {
			Type type = queryParameters.getFilteredPositionalParameterTypes()[i];
			Object value = queryParameters.getFilteredPositionalParameterValues()[i];
			type.nullSafeSet( st, value, position, session );
			position += type.getColumnSpan( getFactory() );
		}

		return position;
	
protected intbindParameterValues(java.sql.PreparedStatement statement, org.hibernate.engine.QueryParameters queryParameters, int startIndex, org.hibernate.engine.SessionImplementor session)
We specifically override this method here, because in general we know much more about the parameters and their appropriate bind positions here then we do in our super because we track them explciitly here through the ParameterSpecification interface.

param
queryParameters The encapsulation of the parameter values to be bound.
param
startIndex The position from which to start binding parameter values.
param
session The originating session.
return
The number of JDBC bind positions actually bound during this method execution.
throws
SQLException Indicates problems performing the binding.

		int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
		List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
		Iterator itr = parameterSpecs.iterator();
		while ( itr.hasNext() ) {
			ParameterSpecification spec = ( ParameterSpecification ) itr.next();
			position += spec.bind( statement, queryParameters, session, position );
		}
		return position - startIndex;
	
private voidcheckQuery(org.hibernate.engine.QueryParameters queryParameters)

		if ( hasSelectNew() && queryParameters.getResultTransformer() != null ) {
			throw new QueryException( "ResultTransformer is not allowed for 'select new' queries." );
		}
	
public java.lang.String[]getAliases()

		return sqlAliases;
	
protected int[]getCollectionOwners()

		return collectionOwners;
	
protected org.hibernate.persister.collection.CollectionPersister[]getCollectionPersisters()
An (optional) persister for a collection to be initialized; only collection loaders return a non-null value

		return collectionPersisters;
	
public java.lang.String[]getCollectionSuffixes()

		return collectionSuffixes;
	
protected boolean[]getEntityEagerPropertyFetches()

		return entityEagerPropertyFetches;
	
public org.hibernate.persister.entity.Loadable[]getEntityPersisters()

		return entityPersisters;
	
protected org.hibernate.LockMode[]getLockModes(java.util.Map lockModes)

param
lockModes a collection of lock modes specified dynamically via the Query interface


		if ( lockModes==null || lockModes.size()==0 ) {
			return defaultLockModes;
		}
		else {
			// unfortunately this stuff can't be cached because
			// it is per-invocation, not constant for the
			// QueryTranslator instance

			LockMode[] lockModeArray = new LockMode[entityAliases.length];
			for ( int i = 0; i < entityAliases.length; i++ ) {
				LockMode lockMode = (LockMode) lockModes.get( entityAliases[i] );
				if ( lockMode == null ) {
					//NONE, because its the requested lock mode, not the actual!
					lockMode = LockMode.NONE;
				}
				lockModeArray[i] = lockMode;
			}
			return lockModeArray;
		}
	
public int[]getNamedParameterLocs(java.lang.String name)
Returns the locations of all occurrences of the named parameter.

		return queryTranslator.getParameterTranslations().getNamedParameterSqlLocations( name );
	
protected org.hibernate.type.EntityType[]getOwnerAssociationTypes()

		return ownerAssociationTypes;
	
protected int[]getOwners()
An array of indexes of the entity that owns a one-to-one association to the entity at the given index (-1 if there is no "owner")

		return owners;
	
protected java.lang.StringgetQueryIdentifier()

		return queryTranslator.getQueryIdentifier();
	
protected java.lang.ObjectgetResultColumnOrRow(java.lang.Object[] row, org.hibernate.transform.ResultTransformer transformer, java.sql.ResultSet rs, org.hibernate.engine.SessionImplementor session)


		row = toResultRow( row );
		boolean hasTransform = hasSelectNew() || transformer!=null;
		if ( hasScalars ) {
			String[][] scalarColumns = scalarColumnNames;
			int queryCols = queryReturnTypes.length;
			if ( !hasTransform && queryCols == 1 ) {
				return queryReturnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null );
			}
			else {
				row = new Object[queryCols];
				for ( int i = 0; i < queryCols; i++ ) {
					row[i] = queryReturnTypes[i].nullSafeGet( rs, scalarColumns[i], session, null );
				}
				return row;
			}
		}
		else if ( !hasTransform ) {
			return row.length == 1 ? row[0] : row;
		}
		else {
			return row;
		}

	
protected java.util.ListgetResultList(java.util.List results, org.hibernate.transform.ResultTransformer resultTransformer)

		// meant to handle dynamic instantiation queries...
		HolderInstantiator holderInstantiator = HolderInstantiator.getHolderInstantiator(selectNewTransformer, resultTransformer, queryReturnAliases);
		if ( holderInstantiator.isRequired() ) {
			for ( int i = 0; i < results.size(); i++ ) {
				Object[] row = ( Object[] ) results.get( i );
				Object result = holderInstantiator.instantiate(row);
				results.set( i, result );
			}

			if(!hasSelectNew() && resultTransformer!=null) {
				return resultTransformer.transformList(results);
			} else {
				return results;
			}
		} else {
			return results;
		}
	
protected java.lang.StringgetSQLString()
The SQL query string to be called.

		return queryTranslator.getSQLString();
	
public java.lang.String[]getSqlAliasSuffixes()

		return sqlAliasSuffixes;
	
public java.lang.String[]getSuffixes()

		return getSqlAliasSuffixes();
	
private booleanhasSelectNew()

		return selectNewTransformer!=null;
	
private voidinitialize(org.hibernate.hql.ast.tree.SelectClause selectClause)


		List fromElementList = selectClause.getFromElementsForLoad();

		hasScalars = selectClause.isScalarSelect();
		scalarColumnNames = selectClause.getColumnNames();
		//sqlResultTypes = selectClause.getSqlResultTypes();
		queryReturnTypes = selectClause.getQueryReturnTypes();

		selectNewTransformer = HolderInstantiator.createSelectNewTransformer(
				selectClause.getConstructor(),
				selectClause.isMap(),
				selectClause.isList());
		queryReturnAliases = selectClause.getQueryReturnAliases();

		List collectionFromElements = selectClause.getCollectionFromElements();
		if ( collectionFromElements != null && collectionFromElements.size()!=0 ) {
			int length = collectionFromElements.size();
			collectionPersisters = new QueryableCollection[length];
			collectionOwners = new int[length];
			collectionSuffixes = new String[length];
			for ( int i=0; i<length; i++ ) {
				FromElement collectionFromElement = (FromElement) collectionFromElements.get(i);
				collectionPersisters[i] = collectionFromElement.getQueryableCollection();
				collectionOwners[i] = fromElementList.indexOf( collectionFromElement.getOrigin() );
//				collectionSuffixes[i] = collectionFromElement.getColumnAliasSuffix();
//				collectionSuffixes[i] = Integer.toString( i ) + "_";
				collectionSuffixes[i] = collectionFromElement.getCollectionSuffix();
			}
		}

		int size = fromElementList.size();
		entityPersisters = new Queryable[size];
		entityEagerPropertyFetches = new boolean[size];
		entityAliases = new String[size];
		sqlAliases = new String[size];
		sqlAliasSuffixes = new String[size];
		includeInSelect = new boolean[size];
		owners = new int[size];
		ownerAssociationTypes = new EntityType[size];

		for ( int i = 0; i < size; i++ ) {
			final FromElement element = ( FromElement ) fromElementList.get( i );
			entityPersisters[i] = ( Queryable ) element.getEntityPersister();

			if ( entityPersisters[i] == null ) {
				throw new IllegalStateException( "No entity persister for " + element.toString() );
			}

			entityEagerPropertyFetches[i] = element.isAllPropertyFetch();
			sqlAliases[i] = element.getTableAlias();
			entityAliases[i] = element.getClassAlias();
			sqlAliasByEntityAlias.put( entityAliases[i], sqlAliases[i] );
			// TODO should we just collect these like with the collections above?
			sqlAliasSuffixes[i] = ( size == 1 ) ? "" : Integer.toString( i ) + "_";
//			sqlAliasSuffixes[i] = element.getColumnAliasSuffix();
			includeInSelect[i] = !element.isFetch();
			if ( includeInSelect[i] ) {
				selectLength++;
			}

			owners[i] = -1; //by default
			if ( element.isFetch() ) {
				if ( element.isCollectionJoin() || element.getQueryableCollection() != null ) {
					// This is now handled earlier in this method.
				}
				else if ( element.getDataType().isEntityType() ) {
					EntityType entityType = ( EntityType ) element.getDataType();
					if ( entityType.isOneToOne() ) {
						owners[i] = fromElementList.indexOf( element.getOrigin() );
					}
					ownerAssociationTypes[i] = entityType;
				}
			}
		}

		//NONE, because its the requested lock mode, not the actual!
		defaultLockModes = ArrayHelper.fillArray(LockMode.NONE, size);

	
protected booleanisSubselectLoadingEnabled()

		return hasSubselectLoadableCollections();
	
public java.util.Iteratoriterate(org.hibernate.engine.QueryParameters queryParameters, org.hibernate.event.EventSource session)

		checkQuery( queryParameters );
		final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
		long startTime = 0;
		if ( stats ) {
			startTime = System.currentTimeMillis();
		}

		try {

			final PreparedStatement st = prepareQueryStatement( queryParameters, false, session );

			if(queryParameters.isCallable()) {
				throw new QueryException("iterate() not supported for callable statements");
			}
			final ResultSet rs = getResultSet(st, queryParameters.hasAutoDiscoverScalarTypes(), false, queryParameters.getRowSelection(), session);
			final Iterator result = new IteratorImpl(
					rs,
			        st,
			        session,
			        queryReturnTypes,
			        queryTranslator.getColumnNames(),
			        HolderInstantiator.getHolderInstantiator(selectNewTransformer, queryParameters.getResultTransformer(), queryReturnAliases)
				);

			if ( stats ) {
				session.getFactory().getStatisticsImplementor().queryExecuted(
//						"HQL: " + queryTranslator.getQueryString(),
						getQueryIdentifier(),
						0,
						System.currentTimeMillis() - startTime
				);
			}

			return result;

		}
		catch ( SQLException sqle ) {
			throw JDBCExceptionHelper.convert(
					getFactory().getSQLExceptionConverter(),
			        sqle,
			        "could not execute query using iterate",
			        getSQLString()
				);
		}

	
public java.util.Listlist(org.hibernate.engine.SessionImplementor session, org.hibernate.engine.QueryParameters queryParameters)

		checkQuery( queryParameters );
		return list( session, queryParameters, queryTranslator.getQuerySpaces(), queryReturnTypes );
	
protected booleanneedsFetchingScroll()

		return queryTranslator.containsCollectionFetches();
	
public org.hibernate.ScrollableResultsscroll(org.hibernate.engine.QueryParameters queryParameters, org.hibernate.engine.SessionImplementor session)

		checkQuery( queryParameters );
		return scroll( queryParameters, queryReturnTypes, HolderInstantiator.getHolderInstantiator(selectNewTransformer, queryParameters.getResultTransformer(), queryReturnAliases), session );
	
private java.lang.Object[]toResultRow(java.lang.Object[] row)

		if ( selectLength == row.length ) {
			return row;
		}
		else {
			Object[] result = new Object[selectLength];
			int j = 0;
			for ( int i = 0; i < row.length; i++ ) {
				if ( includeInSelect[i] ) {
					result[j++] = row[i];
				}
			}
			return result;
		}
	
protected booleanupgradeLocks()

		return true;
	
public final voidvalidateScrollability()

		queryTranslator.validateScrollability();