
org.hibernate.hql.classic.QueryTranslatorImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate Show documentation
Show all versions of hibernate Show documentation
Relational Persistence for Java
//$Id: QueryTranslatorImpl.java 11081 2007-01-23 16:31:13Z [email protected] $
package org.hibernate.hql.classic;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.SequencedHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.ScrollableResults;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.JoinSequence;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.event.EventSource;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.FilterTranslator;
import org.hibernate.hql.HolderInstantiator;
import org.hibernate.hql.NameGenerator;
import org.hibernate.hql.ParameterTranslations;
import org.hibernate.impl.IteratorImpl;
import org.hibernate.loader.BasicLoader;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.QuerySelect;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;
/**
* An instance of QueryTranslator translates a Hibernate
* query string to SQL.
*/
public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator {
private static final String[] NO_RETURN_ALIASES = new String[] {};
private final String queryIdentifier;
private final String queryString;
private final Map typeMap = new SequencedHashMap();
private final Map collections = new SequencedHashMap();
private List returnedTypes = new ArrayList();
private final List fromTypes = new ArrayList();
private final List scalarTypes = new ArrayList();
private final Map namedParameters = new HashMap();
private final Map aliasNames = new HashMap();
private final Map oneToOneOwnerNames = new HashMap();
private final Map uniqueKeyOwnerReferences = new HashMap();
private final Map decoratedPropertyMappings = new HashMap();
private final List scalarSelectTokens = new ArrayList();
private final List whereTokens = new ArrayList();
private final List havingTokens = new ArrayList();
private final Map joins = new SequencedHashMap();
private final List orderByTokens = new ArrayList();
private final List groupByTokens = new ArrayList();
private final Set querySpaces = new HashSet();
private final Set entitiesToFetch = new HashSet();
private final Map pathAliases = new HashMap();
private final Map pathJoins = new HashMap();
private Queryable[] persisters;
private int[] owners;
private EntityType[] ownerAssociationTypes;
private String[] names;
private boolean[] includeInSelect;
private int selectLength;
private Type[] returnTypes;
private Type[] actualReturnTypes;
private String[][] scalarColumnNames;
private Map tokenReplacements;
private int nameCount = 0;
private int parameterCount = 0;
private boolean distinct = false;
private boolean compiled;
private String sqlString;
private Class holderClass;
private Constructor holderConstructor;
private boolean hasScalars;
private boolean shallowQuery;
private QueryTranslatorImpl superQuery;
private QueryableCollection collectionPersister;
private int collectionOwnerColumn = -1;
private String collectionOwnerName;
private String fetchName;
private String[] suffixes;
private Map enabledFilters;
private static final Log log = LogFactory.getLog( QueryTranslatorImpl.class );
/**
* Construct a query translator
*
* @param queryIdentifier A unique identifier for the query of which this
* translation is part; typically this is the original, user-supplied query string.
* @param queryString The "preprocessed" query string; at the very least
* already processed by {@link org.hibernate.hql.QuerySplitter}.
* @param enabledFilters Any enabled filters.
* @param factory The session factory.
*/
public QueryTranslatorImpl(
String queryIdentifier,
String queryString,
Map enabledFilters,
SessionFactoryImplementor factory) {
super( factory );
this.queryIdentifier = queryIdentifier;
this.queryString = queryString;
this.enabledFilters = enabledFilters;
}
/**
* Construct a query translator; this form used internally.
*
* @param queryString The query string to process.
* @param enabledFilters Any enabled filters.
* @param factory The session factory.
*/
public QueryTranslatorImpl(
String queryString,
Map enabledFilters,
SessionFactoryImplementor factory) {
this( queryString, queryString, enabledFilters, factory );
}
/**
* Compile a subquery.
*
* @param superquery The containing query of the query to be compiled.
*
* @throws org.hibernate.MappingException Indicates problems resolving
* things referenced in the query.
* @throws org.hibernate.QueryException Generally some form of syntatic
* failure.
*/
void compile(QueryTranslatorImpl superquery) throws QueryException, MappingException {
this.tokenReplacements = superquery.tokenReplacements;
this.superQuery = superquery;
this.shallowQuery = true;
this.enabledFilters = superquery.getEnabledFilters();
compile();
}
/**
* Compile a "normal" query. This method may be called multiple
* times. Subsequent invocations are no-ops.
*/
public synchronized void compile(
Map replacements,
boolean scalar) throws QueryException, MappingException {
if ( !compiled ) {
this.tokenReplacements = replacements;
this.shallowQuery = scalar;
compile();
}
}
/**
* Compile a filter. This method may be called multiple
* times. Subsequent invocations are no-ops.
*/
public synchronized void compile(
String collectionRole,
Map replacements,
boolean scalar) throws QueryException, MappingException {
if ( !isCompiled() ) {
addFromAssociation( "this", collectionRole );
compile( replacements, scalar );
}
}
/**
* Compile the query (generate the SQL).
*
* @throws org.hibernate.MappingException Indicates problems resolving
* things referenced in the query.
* @throws org.hibernate.QueryException Generally some form of syntatic
* failure.
*/
private void compile() throws QueryException, MappingException {
log.trace( "compiling query" );
try {
ParserHelper.parse( new PreprocessingParser( tokenReplacements ),
queryString,
ParserHelper.HQL_SEPARATORS,
this );
renderSQL();
}
catch ( QueryException qe ) {
qe.setQueryString( queryString );
throw qe;
}
catch ( MappingException me ) {
throw me;
}
catch ( Exception e ) {
log.debug( "unexpected query compilation problem", e );
e.printStackTrace();
QueryException qe = new QueryException( "Incorrect query syntax", e );
qe.setQueryString( queryString );
throw qe;
}
postInstantiate();
compiled = true;
}
public String getSQLString() {
return sqlString;
}
public List collectSqlStrings() {
return ArrayHelper.toList( new String[] { sqlString } );
}
public String getQueryString() {
return queryString;
}
/**
* Persisters for the return values of a find() style query.
*
* @return an array of EntityPersisters.
*/
protected Loadable[] getEntityPersisters() {
return persisters;
}
/**
* Types of the return values of an iterate() style query.
*
* @return an array of Types.
*/
public Type[] getReturnTypes() {
return actualReturnTypes;
}
public String[] getReturnAliases() {
// return aliases not supported in classic translator!
return NO_RETURN_ALIASES;
}
public String[][] getColumnNames() {
return scalarColumnNames;
}
private static void logQuery(String hql, String sql) {
if ( log.isDebugEnabled() ) {
log.debug( "HQL: " + hql );
log.debug( "SQL: " + sql );
}
}
void setAliasName(String alias, String name) {
aliasNames.put( alias, name );
}
public String getAliasName(String alias) {
String name = ( String ) aliasNames.get( alias );
if ( name == null ) {
if ( superQuery != null ) {
name = superQuery.getAliasName( alias );
}
else {
name = alias;
}
}
return name;
}
String unalias(String path) {
String alias = StringHelper.root( path );
String name = getAliasName( alias );
if ( name != null ) {
return name + path.substring( alias.length() );
}
else {
return path;
}
}
void addEntityToFetch(String name, String oneToOneOwnerName, AssociationType ownerAssociationType) {
addEntityToFetch( name );
if ( oneToOneOwnerName != null ) oneToOneOwnerNames.put( name, oneToOneOwnerName );
if ( ownerAssociationType != null ) uniqueKeyOwnerReferences.put( name, ownerAssociationType );
}
private void addEntityToFetch(String name) {
entitiesToFetch.add( name );
}
private int nextCount() {
return ( superQuery == null ) ? nameCount++ : superQuery.nameCount++;
}
String createNameFor(String type) {
return StringHelper.generateAlias( type, nextCount() );
}
String createNameForCollection(String role) {
return StringHelper.generateAlias( role, nextCount() );
}
private String getType(String name) {
String type = ( String ) typeMap.get( name );
if ( type == null && superQuery != null ) {
type = superQuery.getType( name );
}
return type;
}
private String getRole(String name) {
String role = ( String ) collections.get( name );
if ( role == null && superQuery != null ) {
role = superQuery.getRole( name );
}
return role;
}
boolean isName(String name) {
return aliasNames.containsKey( name ) ||
typeMap.containsKey( name ) ||
collections.containsKey( name ) || (
superQuery != null && superQuery.isName( name )
);
}
PropertyMapping getPropertyMapping(String name) throws QueryException {
PropertyMapping decorator = getDecoratedPropertyMapping( name );
if ( decorator != null ) return decorator;
String type = getType( name );
if ( type == null ) {
String role = getRole( name );
if ( role == null ) {
throw new QueryException( "alias not found: " + name );
}
return getCollectionPersister( role ); //.getElementPropertyMapping();
}
else {
Queryable persister = getEntityPersister( type );
if ( persister == null ) throw new QueryException( "persistent class not found: " + type );
return persister;
}
}
private PropertyMapping getDecoratedPropertyMapping(String name) {
return ( PropertyMapping ) decoratedPropertyMappings.get( name );
}
void decoratePropertyMapping(String name, PropertyMapping mapping) {
decoratedPropertyMappings.put( name, mapping );
}
private Queryable getEntityPersisterForName(String name) throws QueryException {
String type = getType( name );
Queryable persister = getEntityPersister( type );
if ( persister == null ) throw new QueryException( "persistent class not found: " + type );
return persister;
}
Queryable getEntityPersisterUsingImports(String className) {
final String importedClassName = getFactory().getImportedClassName( className );
if ( importedClassName == null ) {
return null;
}
try {
return ( Queryable ) getFactory().getEntityPersister( importedClassName );
}
catch ( MappingException me ) {
return null;
}
}
Queryable getEntityPersister(String entityName) throws QueryException {
try {
return ( Queryable ) getFactory().getEntityPersister( entityName );
}
catch ( Exception e ) {
throw new QueryException( "persistent class not found: " + entityName );
}
}
QueryableCollection getCollectionPersister(String role) throws QueryException {
try {
return ( QueryableCollection ) getFactory().getCollectionPersister( role );
}
catch ( ClassCastException cce ) {
throw new QueryException( "collection role is not queryable: " + role );
}
catch ( Exception e ) {
throw new QueryException( "collection role not found: " + role );
}
}
void addType(String name, String type) {
typeMap.put( name, type );
}
void addCollection(String name, String role) {
collections.put( name, role );
}
void addFrom(String name, String type, JoinSequence joinSequence)
throws QueryException {
addType( name, type );
addFrom( name, joinSequence );
}
void addFromCollection(String name, String collectionRole, JoinSequence joinSequence)
throws QueryException {
//register collection role
addCollection( name, collectionRole );
addJoin( name, joinSequence );
}
void addFrom(String name, JoinSequence joinSequence)
throws QueryException {
fromTypes.add( name );
addJoin( name, joinSequence );
}
void addFromClass(String name, Queryable classPersister)
throws QueryException {
JoinSequence joinSequence = new JoinSequence( getFactory() )
.setRoot( classPersister, name );
//crossJoins.add(name);
addFrom( name, classPersister.getEntityName(), joinSequence );
}
void addSelectClass(String name) {
returnedTypes.add( name );
}
void addSelectScalar(Type type) {
scalarTypes.add( type );
}
void appendWhereToken(String token) {
whereTokens.add( token );
}
void appendHavingToken(String token) {
havingTokens.add( token );
}
void appendOrderByToken(String token) {
orderByTokens.add( token );
}
void appendGroupByToken(String token) {
groupByTokens.add( token );
}
void appendScalarSelectToken(String token) {
scalarSelectTokens.add( token );
}
void appendScalarSelectTokens(String[] tokens) {
scalarSelectTokens.add( tokens );
}
void addFromJoinOnly(String name, JoinSequence joinSequence) throws QueryException {
addJoin( name, joinSequence.getFromPart() );
}
void addJoin(String name, JoinSequence joinSequence) throws QueryException {
if ( !joins.containsKey( name ) ) joins.put( name, joinSequence );
}
void addNamedParameter(String name) {
if ( superQuery != null ) superQuery.addNamedParameter( name );
Integer loc = new Integer( parameterCount++ );
Object o = namedParameters.get( name );
if ( o == null ) {
namedParameters.put( name, loc );
}
else if ( o instanceof Integer ) {
ArrayList list = new ArrayList( 4 );
list.add( o );
list.add( loc );
namedParameters.put( name, list );
}
else {
( ( ArrayList ) o ).add( loc );
}
}
public int[] getNamedParameterLocs(String name) throws QueryException {
Object o = namedParameters.get( name );
if ( o == null ) {
QueryException qe = new QueryException( ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name );
qe.setQueryString( queryString );
throw qe;
}
if ( o instanceof Integer ) {
return new int[]{ ( ( Integer ) o ).intValue() };
}
else {
return ArrayHelper.toIntArray( ( ArrayList ) o );
}
}
private void renderSQL() throws QueryException, MappingException {
final int rtsize;
if ( returnedTypes.size() == 0 && scalarTypes.size() == 0 ) {
//ie no select clause in HQL
returnedTypes = fromTypes;
rtsize = returnedTypes.size();
}
else {
rtsize = returnedTypes.size();
Iterator iter = entitiesToFetch.iterator();
while ( iter.hasNext() ) {
returnedTypes.add( iter.next() );
}
}
int size = returnedTypes.size();
persisters = new Queryable[size];
names = new String[size];
owners = new int[size];
ownerAssociationTypes = new EntityType[size];
suffixes = new String[size];
includeInSelect = new boolean[size];
for ( int i = 0; i < size; i++ ) {
String name = ( String ) returnedTypes.get( i );
//if ( !isName(name) ) throw new QueryException("unknown type: " + name);
persisters[i] = getEntityPersisterForName( name );
// TODO: cannot use generateSuffixes() - it handles the initial suffix differently.
suffixes[i] = ( size == 1 ) ? "" : Integer.toString( i ) + '_';
names[i] = name;
includeInSelect[i] = !entitiesToFetch.contains( name );
if ( includeInSelect[i] ) selectLength++;
if ( name.equals( collectionOwnerName ) ) collectionOwnerColumn = i;
String oneToOneOwner = ( String ) oneToOneOwnerNames.get( name );
owners[i] = ( oneToOneOwner == null ) ? -1 : returnedTypes.indexOf( oneToOneOwner );
ownerAssociationTypes[i] = (EntityType) uniqueKeyOwnerReferences.get( name );
}
if ( ArrayHelper.isAllNegative( owners ) ) owners = null;
String scalarSelect = renderScalarSelect(); //Must be done here because of side-effect! yuck...
int scalarSize = scalarTypes.size();
hasScalars = scalarTypes.size() != rtsize;
returnTypes = new Type[scalarSize];
for ( int i = 0; i < scalarSize; i++ ) {
returnTypes[i] = ( Type ) scalarTypes.get( i );
}
QuerySelect sql = new QuerySelect( getFactory().getDialect() );
sql.setDistinct( distinct );
if ( !shallowQuery ) {
renderIdentifierSelect( sql );
renderPropertiesSelect( sql );
}
if ( collectionPersister != null ) {
sql.addSelectFragmentString( collectionPersister.selectFragment( fetchName, "__" ) );
}
if ( hasScalars || shallowQuery ) sql.addSelectFragmentString( scalarSelect );
//TODO: for some dialects it would be appropriate to add the renderOrderByPropertiesSelect() to other select strings
mergeJoins( sql.getJoinFragment() );
sql.setWhereTokens( whereTokens.iterator() );
sql.setGroupByTokens( groupByTokens.iterator() );
sql.setHavingTokens( havingTokens.iterator() );
sql.setOrderByTokens( orderByTokens.iterator() );
if ( collectionPersister != null && collectionPersister.hasOrdering() ) {
sql.addOrderBy( collectionPersister.getSQLOrderByString( fetchName ) );
}
scalarColumnNames = NameGenerator.generateColumnNames( returnTypes, getFactory() );
// initialize the Set of queried identifier spaces (ie. tables)
Iterator iter = collections.values().iterator();
while ( iter.hasNext() ) {
CollectionPersister p = getCollectionPersister( ( String ) iter.next() );
addQuerySpaces( p.getCollectionSpaces() );
}
iter = typeMap.keySet().iterator();
while ( iter.hasNext() ) {
Queryable p = getEntityPersisterForName( ( String ) iter.next() );
addQuerySpaces( p.getQuerySpaces() );
}
sqlString = sql.toQueryString();
if ( holderClass != null ) holderConstructor = ReflectHelper.getConstructor( holderClass, returnTypes );
if ( hasScalars ) {
actualReturnTypes = returnTypes;
}
else {
actualReturnTypes = new Type[selectLength];
int j = 0;
for ( int i = 0; i < persisters.length; i++ ) {
if ( includeInSelect[i] ) {
actualReturnTypes[j++] = TypeFactory.manyToOne( persisters[i].getEntityName(), shallowQuery );
}
}
}
}
private void renderIdentifierSelect(QuerySelect sql) {
int size = returnedTypes.size();
for ( int k = 0; k < size; k++ ) {
String name = ( String ) returnedTypes.get( k );
String suffix = size == 1 ? "" : Integer.toString( k ) + '_';
sql.addSelectFragmentString( persisters[k].identifierSelectFragment( name, suffix ) );
}
}
/*private String renderOrderByPropertiesSelect() {
StringBuffer buf = new StringBuffer(10);
//add the columns we are ordering by to the select ID select clause
Iterator iter = orderByTokens.iterator();
while ( iter.hasNext() ) {
String token = (String) iter.next();
if ( token.lastIndexOf(".") > 0 ) {
//ie. it is of form "foo.bar", not of form "asc" or "desc"
buf.append(StringHelper.COMMA_SPACE).append(token);
}
}
return buf.toString();
}*/
private void renderPropertiesSelect(QuerySelect sql) {
int size = returnedTypes.size();
for ( int k = 0; k < size; k++ ) {
String suffix = size == 1 ? "" : Integer.toString( k ) + '_';
String name = ( String ) returnedTypes.get( k );
sql.addSelectFragmentString( persisters[k].propertySelectFragment( name, suffix, false ) );
}
}
/**
* WARNING: side-effecty
*/
private String renderScalarSelect() {
boolean isSubselect = superQuery != null;
StringBuffer buf = new StringBuffer( 20 );
if ( scalarTypes.size() == 0 ) {
//ie. no select clause
int size = returnedTypes.size();
for ( int k = 0; k < size; k++ ) {
scalarTypes.add( TypeFactory.manyToOne( persisters[k].getEntityName(), shallowQuery ) );
String[] idColumnNames = persisters[k].getIdentifierColumnNames();
for ( int i = 0; i < idColumnNames.length; i++ ) {
buf.append( returnedTypes.get( k ) ).append( '.' ).append( idColumnNames[i] );
if ( !isSubselect ) buf.append( " as " ).append( NameGenerator.scalarName( k, i ) );
if ( i != idColumnNames.length - 1 || k != size - 1 ) buf.append( ", " );
}
}
}
else {
//there _was_ a select clause
Iterator iter = scalarSelectTokens.iterator();
int c = 0;
boolean nolast = false; //real hacky...
int parenCount = 0; // used to count the nesting of parentheses
while ( iter.hasNext() ) {
Object next = iter.next();
if ( next instanceof String ) {
String token = ( String ) next;
if ( "(".equals( token ) ) {
parenCount++;
}
else if ( ")".equals( token ) ) {
parenCount--;
}
String lc = token.toLowerCase();
if ( lc.equals( ", " ) ) {
if ( nolast ) {
nolast = false;
}
else {
if ( !isSubselect && parenCount == 0 ) {
int x = c++;
buf.append( " as " )
.append( NameGenerator.scalarName( x, 0 ) );
}
}
}
buf.append( token );
if ( lc.equals( "distinct" ) || lc.equals( "all" ) ) {
buf.append( ' ' );
}
}
else {
nolast = true;
String[] tokens = ( String[] ) next;
for ( int i = 0; i < tokens.length; i++ ) {
buf.append( tokens[i] );
if ( !isSubselect ) {
buf.append( " as " )
.append( NameGenerator.scalarName( c, i ) );
}
if ( i != tokens.length - 1 ) buf.append( ", " );
}
c++;
}
}
if ( !isSubselect && !nolast ) {
int x = c++;
buf.append( " as " )
.append( NameGenerator.scalarName( x, 0 ) );
}
}
return buf.toString();
}
private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException {
Iterator iter = joins.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = ( Map.Entry ) iter.next();
String name = ( String ) me.getKey();
JoinSequence join = ( JoinSequence ) me.getValue();
join.setSelector( new JoinSequence.Selector() {
public boolean includeSubclasses(String alias) {
boolean include = returnedTypes.contains( alias ) && !isShallowQuery();
return include;
}
} );
if ( typeMap.containsKey( name ) ) {
ojf.addFragment( join.toJoinFragment( enabledFilters, true ) );
}
else if ( collections.containsKey( name ) ) {
ojf.addFragment( join.toJoinFragment( enabledFilters, true ) );
}
else {
//name from a super query (a bit inelegant that it shows up here)
}
}
}
public final Set getQuerySpaces() {
return querySpaces;
}
/**
* Is this query called by scroll() or iterate()?
*
* @return true if it is, false if it is called by find() or list()
*/
boolean isShallowQuery() {
return shallowQuery;
}
void addQuerySpaces(Serializable[] spaces) {
for ( int i = 0; i < spaces.length; i++ ) {
querySpaces.add( spaces[i] );
}
if ( superQuery != null ) superQuery.addQuerySpaces( spaces );
}
void setDistinct(boolean distinct) {
this.distinct = distinct;
}
boolean isSubquery() {
return superQuery != null;
}
/**
* Overrides method from Loader
*/
public CollectionPersister[] getCollectionPersisters() {
return collectionPersister == null ? null : new CollectionPersister[] { collectionPersister };
}
protected String[] getCollectionSuffixes() {
return collectionPersister == null ? null : new String[] { "__" };
}
void setCollectionToFetch(String role, String name, String ownerName, String entityName)
throws QueryException {
fetchName = name;
collectionPersister = getCollectionPersister( role );
collectionOwnerName = ownerName;
if ( collectionPersister.getElementType().isEntityType() ) {
addEntityToFetch( entityName );
}
}
protected String[] getSuffixes() {
return suffixes;
}
protected String[] getAliases() {
return names;
}
/**
* Used for collection filters
*/
private void addFromAssociation(final String elementName, final String collectionRole)
throws QueryException {
//q.addCollection(collectionName, collectionRole);
QueryableCollection persister = getCollectionPersister( collectionRole );
Type collectionElementType = persister.getElementType();
if ( !collectionElementType.isEntityType() ) {
throw new QueryException( "collection of values in filter: " + elementName );
}
String[] keyColumnNames = persister.getKeyColumnNames();
//if (keyColumnNames.length!=1) throw new QueryException("composite-key collection in filter: " + collectionRole);
String collectionName;
JoinSequence join = new JoinSequence( getFactory() );
collectionName = persister.isOneToMany() ?
elementName :
createNameForCollection( collectionRole );
join.setRoot( persister, collectionName );
if ( !persister.isOneToMany() ) {
//many-to-many
addCollection( collectionName, collectionRole );
try {
join.addJoin( ( AssociationType ) persister.getElementType(),
elementName,
JoinFragment.INNER_JOIN,
persister.getElementColumnNames(collectionName) );
}
catch ( MappingException me ) {
throw new QueryException( me );
}
}
join.addCondition( collectionName, keyColumnNames, " = ?" );
//if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(collectionName) );
EntityType elemType = ( EntityType ) collectionElementType;
addFrom( elementName, elemType.getAssociatedEntityName(), join );
}
String getPathAlias(String path) {
return ( String ) pathAliases.get( path );
}
JoinSequence getPathJoin(String path) {
return ( JoinSequence ) pathJoins.get( path );
}
void addPathAliasAndJoin(String path, String alias, JoinSequence joinSequence) {
pathAliases.put( path, alias );
pathJoins.put( path, joinSequence );
}
public List list(SessionImplementor session, QueryParameters queryParameters)
throws HibernateException {
return list( session, queryParameters, getQuerySpaces(), actualReturnTypes );
}
/**
* Return the query results as an iterator
*/
public Iterator iterate(QueryParameters queryParameters, EventSource session)
throws HibernateException {
boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
long startTime = 0;
if ( stats ) startTime = System.currentTimeMillis();
try {
PreparedStatement st = prepareQueryStatement( queryParameters, false, session );
ResultSet rs = getResultSet( st, queryParameters.hasAutoDiscoverScalarTypes(), false, queryParameters.getRowSelection(), session );
HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator(holderConstructor, queryParameters.getResultTransformer());
Iterator result = new IteratorImpl( rs, st, session, returnTypes, getColumnNames(), hi );
if ( stats ) {
session.getFactory().getStatisticsImplementor().queryExecuted(
"HQL: " + queryString,
0,
System.currentTimeMillis() - startTime
);
}
return result;
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not execute query using iterate",
getSQLString()
);
}
}
public int executeUpdate(QueryParameters queryParameters, SessionImplementor session) throws HibernateException {
throw new UnsupportedOperationException( "Not supported! Use the AST translator...");
}
protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session)
throws SQLException, HibernateException {
row = toResultRow( row );
if ( hasScalars ) {
String[][] scalarColumns = getColumnNames();
int queryCols = returnTypes.length;
if ( holderClass == null && queryCols == 1 ) {
return returnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null );
}
else {
row = new Object[queryCols];
for ( int i = 0; i < queryCols; i++ )
row[i] = returnTypes[i].nullSafeGet( rs, scalarColumns[i], session, null );
return row;
}
}
else if ( holderClass == null ) {
return row.length == 1 ? row[0] : row;
}
else {
return row;
}
}
protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException {
if ( holderClass != null ) {
for ( int i = 0; i < results.size(); i++ ) {
Object[] row = ( Object[] ) results.get( i );
try {
results.set( i, holderConstructor.newInstance( row ) );
}
catch ( Exception e ) {
throw new QueryException( "could not instantiate: " + holderClass, e );
}
}
}
return results;
}
private Object[] toResultRow(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;
}
}
void setHolderClass(Class clazz) {
holderClass = clazz;
}
protected LockMode[] getLockModes(Map lockModes) {
// unfortunately this stuff can't be cached because
// it is per-invocation, not constant for the
// QueryTranslator instance
HashMap nameLockModes = new HashMap();
if ( lockModes != null ) {
Iterator iter = lockModes.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = ( Map.Entry ) iter.next();
nameLockModes.put( getAliasName( ( String ) me.getKey() ),
me.getValue() );
}
}
LockMode[] lockModeArray = new LockMode[names.length];
for ( int i = 0; i < names.length; i++ ) {
LockMode lm = ( LockMode ) nameLockModes.get( names[i] );
if ( lm == null ) lm = LockMode.NONE;
lockModeArray[i] = lm;
}
return lockModeArray;
}
protected String applyLocks(String sql, Map lockModes, Dialect dialect) throws QueryException {
// can't cache this stuff either (per-invocation)
final String result;
if ( lockModes == null || lockModes.size() == 0 ) {
result = sql;
}
else {
Map aliasedLockModes = new HashMap();
Iterator iter = lockModes.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = ( Map.Entry ) iter.next();
aliasedLockModes.put( getAliasName( ( String ) me.getKey() ), me.getValue() );
}
Map keyColumnNames = null;
if ( dialect.forUpdateOfColumns() ) {
keyColumnNames = new HashMap();
for ( int i = 0; i < names.length; i++ ) {
keyColumnNames.put( names[i], persisters[i].getIdentifierColumnNames() );
}
}
result = dialect.applyLocksToSql( sql, aliasedLockModes, keyColumnNames );
}
logQuery( queryString, result );
return result;
}
protected boolean upgradeLocks() {
return true;
}
protected int[] getCollectionOwners() {
return new int[] { collectionOwnerColumn };
}
protected boolean isCompiled() {
return compiled;
}
public String toString() {
return queryString;
}
protected int[] getOwners() {
return owners;
}
protected EntityType[] getOwnerAssociationTypes() {
return ownerAssociationTypes;
}
public Class getHolderClass() {
return holderClass;
}
public Map getEnabledFilters() {
return enabledFilters;
}
public ScrollableResults scroll(final QueryParameters queryParameters,
final SessionImplementor session)
throws HibernateException {
HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator(holderConstructor, queryParameters.getResultTransformer());
return scroll( queryParameters, returnTypes, hi, session );
}
public String getQueryIdentifier() {
return queryIdentifier;
}
protected boolean isSubselectLoadingEnabled() {
return hasSubselectLoadableCollections();
}
public void validateScrollability() throws HibernateException {
// This is the legacy behaviour for HQL queries...
if ( getCollectionPersisters() != null ) {
throw new HibernateException( "Cannot scroll queries which initialize collections" );
}
}
public boolean containsCollectionFetches() {
return false;
}
public boolean isManipulationStatement() {
// classic parser does not support bulk manipulation statements
return false;
}
public ParameterTranslations getParameterTranslations() {
return new ParameterTranslations() {
public boolean supportsOrdinalParameterMetadata() {
// classic translator does not support collection of ordinal
// param metadata
return false;
}
public int getOrdinalParameterCount() {
return 0; // not known!
}
public int getOrdinalParameterSqlLocation(int ordinalPosition) {
return 0; // not known!
}
public Type getOrdinalParameterExpectedType(int ordinalPosition) {
return null; // not known!
}
public Set getNamedParameterNames() {
return namedParameters.keySet();
}
public int[] getNamedParameterSqlLocations(String name) {
return getNamedParameterLocs( name );
}
public Type getNamedParameterExpectedType(String name) {
return null; // not known!
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy