Author: max...@jb... Date: 2006-03-16 09:14:48 -0500 (Thu, 16 Mar 2006) New Revision: 9636 Modified: trunk/Hibernate3/src/org/hibernate/Query.java trunk/Hibernate3/src/org/hibernate/cache/QueryKey.java trunk/Hibernate3/src/org/hibernate/engine/QueryParameters.java trunk/Hibernate3/src/org/hibernate/hql/HolderInstantiator.java trunk/Hibernate3/src/org/hibernate/hql/classic/QueryTranslatorImpl.java trunk/Hibernate3/src/org/hibernate/impl/AbstractQueryImpl.java trunk/Hibernate3/src/org/hibernate/loader/Loader.java trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaLoader.java trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java trunk/Hibernate3/src/org/hibernate/loader/custom/CustomLoader.java trunk/Hibernate3/src/org/hibernate/loader/custom/CustomQuery.java trunk/Hibernate3/src/org/hibernate/loader/custom/SQLCustomQuery.java trunk/Hibernate3/src/org/hibernate/loader/entity/AbstractEntityLoader.java trunk/Hibernate3/src/org/hibernate/loader/entity/CollectionElementLoader.java trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java trunk/Hibernate3/test/org/hibernate/test/dom4j/Dom4jTest.java trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java trunk/Hibernate3/test/org/hibernate/test/legacy/FumTest.java trunk/Hibernate3/test/org/hibernate/test/querycache/QueryCacheTest.java trunk/Hibernate3/test/org/hibernate/test/sql/GeneralTest.java Log: HHH-38 Add setResultClass or similar to Criteria and HQL HHH-332 Add ResultTransformer support for HQL HHH-587 Add ResultTransformer for all query methods (HQL, Criteria & SQL) Modified: trunk/Hibernate3/src/org/hibernate/Query.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/Query.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/Query.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -11,6 +11,7 @@ import java.util.List; import java.util.Locale; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; /** @@ -352,6 +353,16 @@ * @param val a non-null instance of a persistent class */ public Query setEntity(String name, Object val); // use setParameter for null values + + + /** + * Set a strategy for handling the query results. This can be used to change + * "shape" of the query result. + * + * @param resultTransformer The transformer to apply + * @return this (for method chaining) + */ + public Query setResultTransformer(ResultTransformer transformer); } Modified: trunk/Hibernate3/src/org/hibernate/cache/QueryKey.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/cache/QueryKey.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/cache/QueryKey.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -8,6 +8,7 @@ import org.hibernate.EntityMode; import org.hibernate.engine.QueryParameters; import org.hibernate.engine.RowSelection; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; import org.hibernate.util.EqualsHelper; @@ -26,6 +27,9 @@ private final Set filters; private final int hashCode; + // the user provided resulttransformer, not the one used with "select new". Here to avoid mangling transformed/non-transformed results. + private final ResultTransformer customTransformer; + public QueryKey(String queryString, QueryParameters queryParameters, Set filters, EntityMode entityMode) { this.sqlQueryString = queryString; this.types = queryParameters.getPositionalParameterTypes(); @@ -42,6 +46,7 @@ this.namedParameters = queryParameters.getNamedParameters(); this.entityMode = entityMode; this.filters = filters; + this.customTransformer = queryParameters.getResultTransformer(); this.hashCode = getHashCode(); } @@ -49,6 +54,7 @@ QueryKey that = (QueryKey) other; if ( !sqlQueryString.equals(that.sqlQueryString) ) return false; if ( !EqualsHelper.equals(firstRow, that.firstRow) || !EqualsHelper.equals(maxRows, that.maxRows) ) return false; + if ( !EqualsHelper.equals(customTransformer, that.customTransformer) ) return false; if (types==null) { if (that.types!=null) return false; } @@ -78,6 +84,7 @@ } result = 37 * result + ( namedParameters==null ? 0 : namedParameters.hashCode() ); result = 37 * result + ( filters==null ? 0 : filters.hashCode() ); + result = 37 * result + ( customTransformer==null ? 0 : customTransformer.hashCode() ); result = 37 * result + sqlQueryString.hashCode(); return result; } @@ -103,6 +110,7 @@ } if (firstRow!=null) buf.append("; first row: ").append(firstRow); if (maxRows!=null) buf.append("; max rows: ").append(maxRows); + if (customTransformer!=null) buf.append("; transformer: ").append(customTransformer); return buf.toString(); } Modified: trunk/Hibernate3/src/org/hibernate/engine/QueryParameters.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/engine/QueryParameters.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/engine/QueryParameters.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -19,6 +19,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.hql.classic.ParserHelper; import org.hibernate.pretty.Printer; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; import org.hibernate.util.ArrayHelper; @@ -46,6 +47,8 @@ private boolean autodiscovertypes = false; private boolean isNaturalKeyLookup; + private final ResultTransformer resultTransformer; // why is all others non final ? + private String processedSQL; private Type[] processedPositionalParameterTypes; private Object[] processedPositionalParameterValues; @@ -84,7 +87,8 @@ false, null, null, - false + false, + null ); } @@ -117,7 +121,8 @@ false, null, null, - collectionKeys + collectionKeys, + null ); } @@ -130,7 +135,8 @@ final String cacheRegion, //final boolean forceCacheRefresh, final String comment, - final boolean isLookupByNaturalKey + final boolean isLookupByNaturalKey, + final ResultTransformer transformer ) { this( positionalParameterTypes, @@ -142,7 +148,8 @@ cacheable, cacheRegion, comment, - null + null, + transformer ); isNaturalKeyLookup = isLookupByNaturalKey; } @@ -158,7 +165,8 @@ final String cacheRegion, //final boolean forceCacheRefresh, final String comment, - final Serializable[] collectionKeys + final Serializable[] collectionKeys, + ResultTransformer transformer ) { this.positionalParameterTypes = positionalParameterTypes; this.positionalParameterValues = positionalParameterValues; @@ -171,6 +179,7 @@ this.comment = comment; this.collectionKeys = collectionKeys; this.readOnly = readOnly; + this.resultTransformer = transformer; } public QueryParameters( @@ -187,7 +196,8 @@ final Serializable[] collectionKeys, final Object optionalObject, final String optionalEntityName, - final Serializable optionalId + final Serializable optionalId, + final ResultTransformer transformer ) { this( positionalParameterTypes, @@ -199,7 +209,8 @@ cacheable, cacheRegion, comment, - collectionKeys + collectionKeys, + transformer ); this.optionalEntityName = optionalEntityName; this.optionalId = optionalId; @@ -225,6 +236,10 @@ public RowSelection getRowSelection() { return rowSelection; } + + public ResultTransformer getResultTransformer() { + return resultTransformer; + } public void setNamedParameters(Map map) { namedParameters = map; @@ -454,11 +469,14 @@ this.collectionKeys, this.optionalObject, this.optionalEntityName, - this.optionalId + this.optionalId, + this.resultTransformer ); copy.processedSQL = this.processedSQL; copy.processedPositionalParameterTypes = this.processedPositionalParameterTypes; copy.processedPositionalParameterValues = this.processedPositionalParameterValues; return copy; } + + } Modified: trunk/Hibernate3/src/org/hibernate/hql/HolderInstantiator.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/hql/HolderInstantiator.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/hql/HolderInstantiator.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -2,65 +2,80 @@ package org.hibernate.hql; import java.lang.reflect.Constructor; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import org.hibernate.QueryException; +import org.hibernate.transform.AliasToBeanConstructorResultTransformer; +import org.hibernate.transform.ResultTransformer; +import org.hibernate.transform.Transformers; /** * @author Gavin King */ public final class HolderInstantiator { + + public static final HolderInstantiator NOOP_INSTANTIATOR = new HolderInstantiator(null,null); - //TODO: have an interface and three different subclasses! - - private final Constructor constructor; - private final boolean returnMaps; - private final boolean returnLists; + private final ResultTransformer transformer; private final String[] queryReturnAliases; + public static HolderInstantiator getHolderInstantiator(ResultTransformer selectNewTransformer, ResultTransformer customTransformer, String[] queryReturnAliases) { + if(selectNewTransformer!=null) { + return new HolderInstantiator(selectNewTransformer, queryReturnAliases); + } else { + return new HolderInstantiator(customTransformer, queryReturnAliases); + } + } + + public static ResultTransformer createSelectNewTransformer(Constructor constructor, boolean returnMaps, boolean returnLists) { + if ( constructor != null ) { + return new AliasToBeanConstructorResultTransformer(constructor); + } + else if ( returnMaps ) { + return Transformers.ALIAS_TO_ENTITY_MAP; + } + else if ( returnLists ) { + return Transformers.TO_LIST; + } + else { + return null; + } + } + + static public HolderInstantiator createClassicHolderInstantiator(Constructor constructor, + ResultTransformer transformer) { + if ( constructor != null ) { + return new HolderInstantiator(new AliasToBeanConstructorResultTransformer(constructor), null); + } + else { + return new HolderInstantiator(transformer, null); + } + } + public HolderInstantiator( - Constructor constructor, - boolean returnMaps, - boolean returnLists, + ResultTransformer transformer, String[] queryReturnAliases ) { - this.constructor = constructor; - this.returnLists = returnLists; - this.returnMaps = returnMaps; + this.transformer = transformer; this.queryReturnAliases = queryReturnAliases; } public boolean isRequired() { - return constructor!=null || returnLists || returnMaps; + return transformer!=null; } public Object instantiate(Object[] row) { - if ( constructor != null ) { - try { - return constructor.newInstance( row ); - } - catch ( Exception e ) { - throw new QueryException( - "could not instantiate: " + - constructor.getDeclaringClass().getName(), - e ); - } - } - else if ( returnMaps ) { - Map map = new HashMap(); - for ( int j = 0; j < row.length; j++ ) { - map.put( queryReturnAliases[j], row[j] ); - } - return map; - } - else if ( returnLists ) { - return Arrays.asList(row); - } - else { + if(transformer==null) { return row; + } else { + return transformer.transformTuple(row, queryReturnAliases); } + } + + public String[] getQueryReturnAliases() { + return queryReturnAliases; } - + + public ResultTransformer getResultTransformer() { + return transformer; + } + } Modified: trunk/Hibernate3/src/org/hibernate/hql/classic/QueryTranslatorImpl.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/hql/classic/QueryTranslatorImpl.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/hql/classic/QueryTranslatorImpl.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -43,6 +43,7 @@ import org.hibernate.sql.ForUpdateFragment; 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; @@ -901,7 +902,7 @@ PreparedStatement st = prepareQueryStatement( queryParameters, false, session ); ResultSet rs = getResultSet( st, queryParameters.hasAutoDiscoverScalarTypes(), false, queryParameters.getRowSelection(), session ); - HolderInstantiator hi = new HolderInstantiator(holderConstructor, false, false, null); + HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator(holderConstructor, queryParameters.getResultTransformer()); Iterator result = new IteratorImpl( rs, st, session, returnTypes, getColumnNames(), hi ); if ( stats ) { @@ -930,7 +931,7 @@ throw new UnsupportedOperationException( "Not supported! Use the AST translator..."); } - protected Object getResultColumnOrRow(Object[] row, ResultSet rs, SessionImplementor session) + protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { row = toResultRow( row ); if ( hasScalars ) { @@ -955,7 +956,7 @@ } - protected List getResultList(List results) throws QueryException { + 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 ); @@ -1071,7 +1072,7 @@ public ScrollableResults scroll(final QueryParameters queryParameters, final SessionImplementor session) throws HibernateException { - HolderInstantiator hi = new HolderInstantiator(holderConstructor, false, false, null); + HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator(holderConstructor, queryParameters.getResultTransformer()); return scroll( queryParameters, returnTypes, hi, session ); } Modified: trunk/Hibernate3/src/org/hibernate/impl/AbstractQueryImpl.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/impl/AbstractQueryImpl.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/impl/AbstractQueryImpl.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -34,6 +34,7 @@ import org.hibernate.hql.classic.ParserHelper; import org.hibernate.property.Getter; import org.hibernate.proxy.HibernateProxyHelper; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.SerializableType; import org.hibernate.type.Type; import org.hibernate.type.TypeFactory; @@ -76,6 +77,7 @@ private CacheMode sessionCacheMode; private Serializable collectionKey; private boolean readOnly; + private ResultTransformer resultTransformer; public AbstractQueryImpl( String queryString, @@ -170,6 +172,11 @@ return this; } + public Query setResultTransformer(ResultTransformer transformer) { + this.resultTransformer = transformer; + return this; + } + public void setOptionalEntityName(String optionalEntityName) { this.optionalEntityName = optionalEntityName; } @@ -791,7 +798,8 @@ collectionKey == null ? null : new Serializable[] { collectionKey }, optionalObject, optionalEntityName, - optionalId + optionalId, + resultTransformer ); } Modified: trunk/Hibernate3/src/org/hibernate/loader/Loader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/Loader.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/Loader.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -5,7 +5,6 @@ import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; @@ -46,8 +45,8 @@ import org.hibernate.event.PreLoadEvent; import org.hibernate.exception.JDBCExceptionHelper; import org.hibernate.hql.HolderInstantiator; +import org.hibernate.impl.FetchingScrollableResultsImpl; import org.hibernate.impl.ScrollableResultsImpl; -import org.hibernate.impl.FetchingScrollableResultsImpl; import org.hibernate.jdbc.ColumnNameCache; import org.hibernate.jdbc.ResultSetWrapper; import org.hibernate.persister.collection.CollectionPersister; @@ -56,6 +55,7 @@ import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.HibernateProxy; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.AssociationType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; @@ -592,7 +592,7 @@ } } - return getResultColumnOrRow( row, resultSet, session ); + return getResultColumnOrRow( row, queryParameters.getResultTransformer(), resultSet, session ); } @@ -867,7 +867,7 @@ .endLoadingCollections( collectionPersister, resultSetId, session ); } - protected List getResultList(List results) throws QueryException { + protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException { return results; } @@ -876,7 +876,7 @@ * This empty implementation merely returns its first argument. This is * overridden by some subclasses. */ - protected Object getResultColumnOrRow(Object[] row, ResultSet rs, SessionImplementor session) + protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { return row; } @@ -2026,7 +2026,7 @@ } private List listIgnoreQueryCache(SessionImplementor session, QueryParameters queryParameters) { - return getResultList( doList( session, queryParameters ) ); + return getResultList( doList( session, queryParameters ), queryParameters.getResultTransformer() ); } private List listUsingQueryCache( @@ -2070,7 +2070,7 @@ ); } - return getResultList( result ); + return getResultList( result, queryParameters.getResultTransformer() ); } private List getResultFromQueryCache( Modified: trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaLoader.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaLoader.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -22,6 +22,7 @@ import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.sql.ForUpdateFragment; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; /** @@ -95,7 +96,7 @@ } - protected Object getResultColumnOrRow(Object[] row, ResultSet rs, SessionImplementor session) + protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { final Object[] result; final String[] aliases; @@ -160,7 +161,7 @@ return hasSubselectLoadableCollections(); } - protected List getResultList(List results) { + protected List getResultList(List results, ResultTransformer resultTransformer) { return translator.getRootCriteria().getResultTransformer() .transformList(results); } Modified: trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/criteria/CriteriaQueryTranslator.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -287,7 +287,8 @@ rootCriteria.getCacheable(), rootCriteria.getCacheRegion(), rootCriteria.getComment(), - rootCriteria.isLookupByNaturalKey() + rootCriteria.isLookupByNaturalKey(), + rootCriteria.getResultTransformer() ); } Modified: trunk/Hibernate3/src/org/hibernate/loader/custom/CustomLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/custom/CustomLoader.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/custom/CustomLoader.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -15,11 +15,13 @@ import org.hibernate.engine.QueryParameters; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionImplementor; +import org.hibernate.hql.HolderInstantiator; import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.EntityAliases; import org.hibernate.loader.Loader; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.Loadable; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; import org.hibernate.type.TypeFactory; import org.hibernate.util.ArrayHelper; @@ -32,6 +34,8 @@ */ public class CustomLoader extends Loader { + // Currently *not* cachable if autodiscover types is in effect (e.g. "select * ...") + private final Type[] resultTypes; private final Loadable[] persisters; private final CollectionPersister[] collectionPersisters; @@ -39,12 +43,15 @@ private Type[] discoveredTypes; private String[] discoveredColumnAliases; private ResultSetMetaData metaData; - + private final String[] queryReturnAliases; + public CustomLoader( CustomQuery customQuery, SessionFactoryImplementor factory) { super(factory); this.customQuery = customQuery; + + queryReturnAliases = customQuery.getReturnAliases(); String[] collectionRoles = customQuery.getCollectionRoles(); if ( collectionRoles==null ) { @@ -107,16 +114,24 @@ public List list( SessionImplementor session, - QueryParameters queryParameters) throws HibernateException { + QueryParameters queryParameters) throws HibernateException { return list(session, queryParameters, customQuery.getQuerySpaces(), resultTypes); } public ScrollableResults scroll( final QueryParameters queryParameters, - final SessionImplementor session) throws HibernateException { - return scroll(queryParameters, resultTypes, null, session); + final SessionImplementor session) throws HibernateException { + return scroll(queryParameters, resultTypes, getHolderInstantiator(queryParameters.getResultTransformer(), getReturnAliasesForTransformer()), session); } + static private HolderInstantiator getHolderInstantiator(ResultTransformer resultTransformer, String[] queryReturnAliases) { + if(resultTransformer!=null) { + return HolderInstantiator.NOOP_INSTANTIATOR; + } else { + return new HolderInstantiator(resultTransformer, queryReturnAliases); + } + } + protected void autoDiscoverTypes(ResultSet rs) { try { metaData = rs.getMetaData(); @@ -170,8 +185,8 @@ protected Object getResultColumnOrRow( Object[] row, - ResultSet rs, - SessionImplementor session) throws SQLException, HibernateException { + ResultTransformer transformer, + ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { Type[] scalarTypes = discoveredTypes==null ? customQuery.getScalarTypes() : discoveredTypes; String[] scalarColumnAliases = discoveredColumnAliases==null ? customQuery.getScalarColumnAliases() : discoveredColumnAliases; @@ -189,21 +204,36 @@ resultRow = row; } + if(transformer!=null) { + return resultRow; + } return resultRow.length == 1 ? resultRow[0] : resultRow; } -// protected Object getResultColumnOrRow( -// Object[] row, -// ResultSet rs, -// SessionImplementor session) throws SQLException, HibernateException { -// if ( persisters.length == 1 ) { -// return row[row.length - 1]; -// } -// else { -// return row; -// } -// } + protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException { + // meant to handle dynamic instantiation queries...(Copy from QueryLoader) + HolderInstantiator holderInstantiator = HolderInstantiator.getHolderInstantiator(null, resultTransformer, getReturnAliasesForTransformer()); + 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 ); + } + + return resultTransformer.transformList(results); + } else { + return results; + } + } + private String[] getReturnAliasesForTransformer() { + if(discoveredColumnAliases!=null) { + return discoveredColumnAliases; + } else { + return queryReturnAliases; + } + } + protected EntityAliases[] getEntityAliases() { return customQuery.getEntityAliases(); } Modified: trunk/Hibernate3/src/org/hibernate/loader/custom/CustomQuery.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/custom/CustomQuery.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/custom/CustomQuery.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -54,5 +54,9 @@ * Optional, may return null */ public String[] getScalarColumnAliases(); + /** + * Optional, may return null + */ + public String[] getReturnAliases(); } Modified: trunk/Hibernate3/src/org/hibernate/loader/custom/SQLCustomQuery.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/custom/SQLCustomQuery.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/custom/SQLCustomQuery.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -44,7 +44,8 @@ private final String[] scalarColumnAliases; private final EntityAliases[] entityDescriptors; private final CollectionAliases[] collectionDescriptors; - + private final String[] returnAliases; + public String getSQL() { return sql; } @@ -130,7 +131,7 @@ collectionOwners = null; } - String[] aliases = ArrayHelper.toStringArray( processor.getAliases() ); + String[] aliases = ArrayHelper.toStringArray( processor.getAliases() ); String[] collAliases = ArrayHelper.toStringArray( processor.getCollectionAliases() ); String[] collSuffixes = ArrayHelper.toStringArray(collectionSuffixes); @@ -141,6 +142,9 @@ scalarColumnAliases = ArrayHelper.toStringArray( processor.getScalarColumnAliases() ); scalarTypes = ArrayHelper.toTypeArray( processor.getScalarTypes() ); + // need to match the "sequence" of what we return. scalar first, entity last. + returnAliases = ArrayHelper.join(scalarColumnAliases, aliases); + String[] suffixes = BasicLoader.generateSuffixes(entityPersisters.length); SQLQueryParser parser = new SQLQueryParser( @@ -221,5 +225,9 @@ this.entityOwners = ownersArray; } + + public String[] getReturnAliases() { + return returnAliases; + } } Modified: trunk/Hibernate3/src/org/hibernate/loader/entity/AbstractEntityLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/entity/AbstractEntityLoader.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/entity/AbstractEntityLoader.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -14,6 +14,7 @@ import org.hibernate.engine.SessionImplementor; import org.hibernate.loader.OuterJoinLoader; import org.hibernate.persister.entity.OuterJoinLoadable; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; public abstract class AbstractEntityLoader extends OuterJoinLoader @@ -76,7 +77,7 @@ } - protected Object getResultColumnOrRow(Object[] row, ResultSet rs, SessionImplementor session) + protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { return row[row.length-1]; } Modified: trunk/Hibernate3/src/org/hibernate/loader/entity/CollectionElementLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/entity/CollectionElementLoader.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/entity/CollectionElementLoader.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -17,6 +17,7 @@ import org.hibernate.loader.OuterJoinLoader; import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.entity.OuterJoinLoadable; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; import org.hibernate.util.ArrayHelper; @@ -96,8 +97,8 @@ protected Object getResultColumnOrRow( Object[] row, - ResultSet rs, - SessionImplementor session) + ResultTransformer transformer, + ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { return row[row.length-1]; } Modified: trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java =================================================================== --- trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/src/org/hibernate/loader/hql/QueryLoader.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -31,6 +31,7 @@ import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Queryable; import org.hibernate.sql.ForUpdateFragment; +import org.hibernate.transform.ResultTransformer; import org.hibernate.type.EntityType; import org.hibernate.type.Type; import org.hibernate.util.ArrayHelper; @@ -74,11 +75,15 @@ private QueryableCollection[] collectionPersisters; private int selectLength; - private HolderInstantiator holderInstantiator; + + private ResultTransformer selectNewTransformer; + private String[] queryReturnAliases; private LockMode[] defaultLockModes; + + /** * Creates a new Loader implementation. * @@ -104,12 +109,11 @@ //sqlResultTypes = selectClause.getSqlResultTypes(); queryReturnTypes = selectClause.getQueryReturnTypes(); - holderInstantiator = new HolderInstantiator( - selectClause.getConstructor(), - selectClause.isMap(), - selectClause.isList(), - selectClause.getQueryReturnAliases() - ); + selectNewTransformer = HolderInstantiator.createSelectNewTransformer( + selectClause.getConstructor(), + selectClause.isMap(), + selectClause.isList()); + queryReturnAliases = selectClause.getQueryReturnAliases(); List collectionFromElements = selectClause.getCollectionFromElements(); if ( collectionFromElements != null && collectionFromElements.size()!=0 ) { @@ -320,15 +324,19 @@ return true; } - protected Object getResultColumnOrRow(Object[] row, ResultSet rs, SessionImplementor session) + private boolean hasSelectNew() { + return selectNewTransformer!=null; + } + + protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { row = toResultRow( row ); - boolean isHolder = holderInstantiator.isRequired(); + boolean hasTransform = hasSelectNew() || transformer!=null; if ( hasScalars ) { String[][] scalarColumns = scalarColumnNames; int queryCols = queryReturnTypes.length; - if ( !isHolder && queryCols == 1 ) { + if ( !hasTransform && queryCols == 1 ) { return queryReturnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null ); } else { @@ -339,7 +347,7 @@ return row; } } - else if ( !isHolder ) { + else if ( !hasTransform ) { return row.length == 1 ? row[0] : row; } else { @@ -348,16 +356,24 @@ } - protected List getResultList(List results) throws QueryException { + protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException { // 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; } - return results; } // --- Query translator methods --- @@ -371,16 +387,23 @@ * @throws HibernateException */ public List list(SessionImplementor session, QueryParameters queryParameters) - throws HibernateException { + throws HibernateException { + checkQuery( queryParameters ); return list( session, queryParameters, queryTranslator.getQuerySpaces(), queryReturnTypes ); } + private void checkQuery(QueryParameters queryParameters) { + if(hasSelectNew() && queryParameters.getResultTransformer()!=null) { + throw new QueryException("ResultTransformer is not allowed for 'select new' queries."); + } + } + /** * Return the query results as an iterator */ public Iterator iterate(QueryParameters queryParameters, EventSource session) throws HibernateException { - + checkQuery( queryParameters ); final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled(); long startTime = 0; if ( stats ) { @@ -401,7 +424,7 @@ session, queryReturnTypes, queryTranslator.getColumnNames(), - holderInstantiator + HolderInstantiator.getHolderInstantiator(selectNewTransformer, queryParameters.getResultTransformer(), queryReturnAliases) ); if ( stats ) { @@ -430,7 +453,8 @@ public ScrollableResults scroll( final QueryParameters queryParameters, final SessionImplementor session) throws HibernateException { - return scroll( queryParameters, queryReturnTypes, holderInstantiator, session ); + checkQuery( queryParameters ); + return scroll( queryParameters, queryReturnTypes, HolderInstantiator.getHolderInstantiator(selectNewTransformer, queryParameters.getResultTransformer(), queryReturnAliases), session ); } // -- Implementation private methods -- Modified: trunk/Hibernate3/test/org/hibernate/test/dom4j/Dom4jTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/dom4j/Dom4jTest.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/test/org/hibernate/test/dom4j/Dom4jTest.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -1,6 +1,8 @@ // $Id$ package org.hibernate.test.dom4j; +import java.util.Map; + import junit.framework.Test; import junit.framework.TestSuite; @@ -16,6 +18,7 @@ import org.hibernate.cfg.Environment; import org.hibernate.criterion.Example; import org.hibernate.test.TestCase; +import org.hibernate.transform.Transformers; /** * @author Gavin King @@ -207,6 +210,17 @@ s = openSession(); t = s.beginTransaction(); + Map m = (Map) s.createQuery( "select a as acc from Account a left join fetch a.customer" ) + .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).uniqueResult(); + acct = (Element)m.get("acc"); + print( acct ); + t.commit(); + s.close(); + + System.out.println(); + + s = openSession(); + t = s.beginTransaction(); acct = (Element) s.createQuery( "from Account" ).uniqueResult(); print( acct ); t.commit(); Modified: trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -11,29 +11,32 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.HashSet; import junit.framework.Test; import junit.framework.TestSuite; import org.hibernate.Hibernate; +import org.hibernate.HibernateException; import org.hibernate.Query; +import org.hibernate.QueryException; import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.QueryException; -import org.hibernate.stat.QueryStatistics; +import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; -import org.hibernate.cfg.Configuration; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.Oracle9Dialect; +import org.hibernate.stat.QueryStatistics; import org.hibernate.test.TestCase; import org.hibernate.test.cid.Customer; import org.hibernate.test.cid.LineItem; import org.hibernate.test.cid.Order; import org.hibernate.test.cid.Product; +import org.hibernate.transform.AliasToBeanResultTransformer; +import org.hibernate.transform.DistinctRootEntityResultTransformer; +import org.hibernate.transform.Transformers; import org.hibernate.type.ManyToOneType; import org.hibernate.type.Type; import org.hibernate.util.StringHelper; @@ -1091,11 +1094,16 @@ List results = session.createQuery( "select new Animal(an.description, an.bodyWeight) from Animal an" ).list(); assertEquals( "Incorrect result size", 2, results.size() ); - assertTrue( "Incorrect return type", results.get( 0 ) instanceof Animal ); - + assertClassAssignability( results.get( 0 ).getClass(), Animal.class ); + Iterator iter = session.createQuery( "select new Animal(an.description, an.bodyWeight) from Animal an" ).iterate(); assertTrue( "Incorrect result size", iter.hasNext() ); - assertTrue( "Incorrect return type", iter.next() instanceof Animal ); + assertTrue( "Incorrect return type", iter.next() instanceof Animal ); + + results = session.createQuery( "select new list(an.description, an.bodyWeight) from Animal an" ).list(); + assertEquals( "Incorrect result size", 2, results.size() ); + assertTrue( "Incorrect return type", results.get( 0 ) instanceof List ); + assertEquals( "Incorrect return type", ( (List) results.get( 0 ) ).size(), 2 ); results = session.createQuery( "select new list(an.description, an.bodyWeight) from Animal an" ).list(); assertEquals( "Incorrect result size", 2, results.size() ); @@ -1108,6 +1116,12 @@ assertTrue( "Incorrect return type", obj instanceof List ); assertEquals( "Incorrect return type", ( (List) obj ).size(), 2 ); + iter = ((org.hibernate.classic.Session)session).iterate( "select new list(an.description, an.bodyWeight) from Animal an" ); + assertTrue( "Incorrect result size", iter.hasNext() ); + obj = iter.next(); + assertTrue( "Incorrect return type", obj instanceof List ); + assertEquals( "Incorrect return type", ( (List) obj ).size(), 2 ); + results = session.createQuery( "select new map(an.description, an.bodyWeight) from Animal an" ).list(); assertEquals( "Incorrect result size", 2, results.size() ); assertTrue( "Incorrect return type", results.get( 0 ) instanceof Map ); @@ -1139,7 +1153,7 @@ assertTrue( "Incorrect result size", sr.next() ); assertTrue( "Incorrect return type", sr.get(0) instanceof Animal ); sr.close(); - + // caching... QueryStatistics stats = getSessions().getStatistics().getQueryStatistics( "select new Animal(an.description, an.bodyWeight) from Animal an" ); results = session.createQuery( "select new Animal(an.description, an.bodyWeight) from Animal an" ) @@ -1160,6 +1174,141 @@ destroyTestBaseData(); } + public void testIllegalMixedTransformerQueries() { + Session session = openSession(); + + try { + getSelectNewQuery( session ).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); + fail("'select new' together with a resulttransformer should result in error!"); + } catch(QueryException he) { + assertTrue(he.getMessage().indexOf("ResultTransformer")==0); + } + + try { + getSelectNewQuery( session ).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).iterate(); + fail("'select new' together with a resulttransformer should result in error!"); + } catch(HibernateException he) { + assertTrue(he.getMessage().indexOf("ResultTransformer")==0); + } + + try { + getSelectNewQuery( session ).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).scroll(); + fail("'select new' together with a resulttransformer should result in error!"); + } catch(HibernateException he) { + assertTrue(he.getMessage().indexOf("ResultTransformer")==0); + } + + session.close(); + } + + private Query getSelectNewQuery(Session session) { + return session.createQuery( "select new Animal(an.description, an.bodyWeight) from Animal an" ); + } + public void testResultTransformerScalarQueries() throws Exception { + + createTestBaseData(); + + String query = "select an.description as description, an.bodyWeight as bodyWeight from Animal an order by bodyWeight desc"; + + Session session = openSession(); + + List results = session.createQuery( query ) + .setResultTransformer(Transformers.aliasToBean(Animal.class)).list(); + assertEquals( "Incorrect result size", results.size(), 2 ); + assertTrue( "Incorrect return type", results.get(0) instanceof Animal ); + Animal firstAnimal = (Animal) results.get(0); + Animal secondAnimal = (Animal) results.get(1); + assertEquals("Mammal #1", firstAnimal.getDescription()); + assertEquals("Mammal #2", secondAnimal.getDescription()); + assertFalse(session.contains(firstAnimal)); + session.close(); + + session = openSession(); + + Iterator iter = session.createQuery( query ) + .setResultTransformer(Transformers.aliasToBean(Animal.class)).iterate(); + assertTrue( "Incorrect result size", iter.hasNext() ); + assertTrue( "Incorrect return type", iter.next() instanceof Animal ); + + session.close(); + + session = openSession(); + + ScrollableResults sr = session.createQuery( query ) + .setResultTransformer(Transformers.aliasToBean(Animal.class)).scroll(); + assertTrue( "Incorrect result size", sr.next() ); + assertTrue( "Incorrect return type", sr.get(0) instanceof Animal ); + assertFalse(session.contains(sr.get(0))); + sr.close(); + + session.close(); + + session = openSession(); + + results = session.createQuery( "select a from Animal a, Animal b" ) + .setResultTransformer(new DistinctRootEntityResultTransformer()) + .list(); + assertEquals( "Incorrect result size", 2, results.size()); + assertTrue( "Incorrect return type", results.get(0) instanceof Animal ); + firstAnimal = (Animal) results.get(0); + secondAnimal = (Animal) results.get(1); + assertEquals("Mammal #1", firstAnimal.getDescription()); + assertEquals("Mammal #2", secondAnimal.getDescription()); + + session.close(); + + destroyTestBaseData(); + } + + public void testResultTransformerEntityQueries() throws Exception { + + createTestBaseData(); + + String query = "select an as an from Animal an order by bodyWeight desc"; + + Session session = openSession(); + + List results = session.createQuery( query ) + .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); + assertEquals( "Incorrect result size", results.size(), 2 ); + assertTrue( "Incorrect return type", results.get(0) instanceof Map ); + Map map = ((Map) results.get(0)); + assertEquals(1, map.size()); + Animal firstAnimal = (Animal) map.get("an"); + map = ((Map) results.get(1)); + Animal secondAnimal = (Animal) map.get("an"); + assertEquals("Mammal #1", firstAnimal.getDescription()); + assertEquals("Mammal #2", secondAnimal.getDescription()); + assertTrue(session.contains(firstAnimal)); + assertSame(firstAnimal, session.get(Animal.class,firstAnimal.getId())); + session.close(); + + session = openSession(); + + Iterator iter = session.createQuery( query ) + .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).iterate(); + assertTrue( "Incorrect result size", iter.hasNext() ); + map = (Map) iter.next(); + firstAnimal = (Animal) map.get("an"); + assertEquals("Mammal #1", firstAnimal.getDescription()); + assertTrue( "Incorrect result size", iter.hasNext() ); + + session.close(); + + session = openSession(); + + ScrollableResults sr = session.createQuery( query ) + .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).scroll(); + assertTrue( "Incorrect result size", sr.next() ); + assertTrue( "Incorrect return type", sr.get(0) instanceof Map ); + assertFalse(session.contains(sr.get(0))); + sr.close(); + + session.close(); + + destroyTestBaseData(); + } + public void testEJBQLFunctions() throws Exception { Session session = openSession(); Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/FumTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/legacy/FumTest.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/test/org/hibernate/test/legacy/FumTest.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -40,6 +40,7 @@ import org.hibernate.dialect.PointbaseDialect; import org.hibernate.dialect.TimesTenDialect; import org.hibernate.transform.AliasToBeanResultTransformer; +import org.hibernate.transform.Transformers; import org.hibernate.type.DateType; import org.hibernate.type.EntityType; import org.hibernate.type.StringType; @@ -223,7 +224,7 @@ Criteria base = s.createCriteria(Fum.class, "fum") .add( Expression.like("fum", "f%") ) - .setResultTransformer(new AliasToBeanResultTransformer(ABean.class)) + .setResultTransformer(Transformers.aliasToBean(ABean.class)) .setFetchMode("friends", FetchMode.JOIN); base.createCriteria("fo", "fo") .add( Expression.eq( "fum", fum.getFo().getFum() ) ); Modified: trunk/Hibernate3/test/org/hibernate/test/querycache/QueryCacheTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/querycache/QueryCacheTest.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/test/org/hibernate/test/querycache/QueryCacheTest.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -2,6 +2,7 @@ package org.hibernate.test.querycache; import java.util.List; +import java.util.Map; import junit.framework.Test; import junit.framework.TestSuite; @@ -15,6 +16,7 @@ import org.hibernate.stat.QueryStatistics; import org.hibernate.stat.CollectionStatistics; import org.hibernate.test.TestCase; +import org.hibernate.transform.Transformers; /** * @author Gavin King @@ -201,6 +203,28 @@ s = openSession(); t = s.beginTransaction(); + result = s.createQuery( queryString ).setCacheable(true).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); + assertEquals( result.size(), 1 ); + Map m = (Map) result.get(0); + assertEquals(1, m.size()); + t.commit(); + s.close(); + + assertEquals( "hit count should not go up since we are adding a resulttransformer", qs.getCacheHitCount(), 1 ); + + s = openSession(); + t = s.beginTransaction(); + result = s.createQuery( queryString ).setCacheable(true).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); + assertEquals( result.size(), 1 ); + m = (Map) result.get(0); + assertEquals(1, m.size()); + t.commit(); + s.close(); + + assertEquals( "hit count should go up since we are using the same resulttransformer", qs.getCacheHitCount(), 2 ); + + s = openSession(); + t = s.beginTransaction(); result = s.createQuery( queryString ).setCacheable(true).list(); assertEquals( result.size(), 1 ); assertTrue( Hibernate.isInitialized( result.get(0) ) ); @@ -210,8 +234,8 @@ t.commit(); s.close(); - assertEquals( qs.getCacheHitCount(), 2 ); - assertEquals( qs.getCacheMissCount(), 2 ); + assertEquals( qs.getCacheHitCount(), 3 ); + assertEquals( qs.getCacheMissCount(), 3 ); Thread.sleep(200); @@ -226,10 +250,10 @@ t.commit(); s.close(); - assertEquals( qs.getCacheHitCount(), 2 ); - assertEquals( qs.getCacheMissCount(), 3 ); - assertEquals( qs.getCachePutCount(), 3 ); - assertEquals( qs.getExecutionCount(), 3 ); + assertEquals( qs.getCacheHitCount(), 3 ); + assertEquals( qs.getCacheMissCount(), 4 ); + assertEquals( qs.getCachePutCount(), 4 ); + assertEquals( qs.getExecutionCount(), 4 ); assertEquals( es.getFetchCount(), 0 ); //check that it was being cached } Modified: trunk/Hibernate3/test/org/hibernate/test/sql/GeneralTest.java =================================================================== --- trunk/Hibernate3/test/org/hibernate/test/sql/GeneralTest.java 2006-03-16 13:56:41 UTC (rev 9635) +++ trunk/Hibernate3/test/org/hibernate/test/sql/GeneralTest.java 2006-03-16 14:14:48 UTC (rev 9636) @@ -3,21 +3,25 @@ import java.io.Serializable; import java.util.Iterator; import java.util.List; +import java.util.Map; -import org.hibernate.test.TestCase; +import junit.framework.Test; +import junit.framework.TestSuite; + import org.hibernate.Hibernate; +import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; -import org.hibernate.HibernateException; import org.hibernate.Transaction; +import org.hibernate.test.TestCase; +import org.hibernate.transform.DistinctRootEntityResultTransformer; +import org.hibernate.transform.Transformers; /** * @author Steve Ebersole */ public class GeneralTest extends TestCase { - // TODO : add this to AllTests once Max verifies; or delete it :) - public GeneralTest(String x) { super( x ); } @@ -100,11 +104,6 @@ .addJoin("emp", "org.employments") .addScalar("regionCode", Hibernate.STRING) .list(); -// List l = s.createSQLQuery("select {org.*}, {emp.*}, emp.regionCode from organization org left outer join employment emp on org.orgid = emp.employer") -// .addEntity("org", Organization.class) -// .addJoin("emp", "org.employments") -// .addScalar("regionCode", Hibernate.STRING) -// .list(); assertEquals( l.size(), 2 ); l = s.createSQLQuery( getOrgEmpPersonSQL() ) @@ -112,13 +111,29 @@ .addJoin("emp", "org.employments") .addJoin("pers", "emp.employee") .list(); -// l = s.createSQLQuery("select {org.*}, {emp.*}, {pers.*} from organization org join employment emp on org.orgid = emp.employer join person pers on pers.perid = emp.employee") -// .addEntity("org", Organization.class) -// .addJoin("emp", "org.employments") -// .addJoin("pers", "emp.employee") -// .list(); assertEquals( l.size(), 1 ); + + t.commit(); + s.close(); + + s = openSession(); + t = s.beginTransaction(); + + l = s.createSQLQuery( "select {org.*}, {emp.*} " + + "from ORGANIZATION org " + + " left outer join EMPLOYMENT emp on org.ORGID = emp.EMPLOYER, ORGANIZATION org2" ) + .addEntity("org", Organization.class) + .addJoin("emp", "org.employments") + .setResultTransformer(new DistinctRootEntityResultTransformer()) + .list(); + assertEquals( l.size(), 2 ); + t.commit(); + s.close(); + + s = openSession(); + t = s.beginTransaction(); + s.delete(emp); s.delete(gavin); s.delete(ifa); @@ -144,17 +159,11 @@ List l = s.createSQLQuery( getOrgEmpRegionSQL() ) .setResultSetMapping( "org-emp-regionCode" ) .list(); -// List l = s.createSQLQuery("select {org.*}, {emp.*}, emp.regionCode from organization org left outer join employment emp on org.orgid = emp.employer") -// .setResultSetMapping( "org-emp-regionCode") -// .list(); assertEquals( l.size(), 2 ); l = s.createSQLQuery( getOrgEmpPersonSQL() ) .setResultSetMapping( "org-emp-person" ) .list(); -// l = s.createSQLQuery("select {org.*}, {emp.*}, {pers.*} from organization org join employment emp on org.orgid = emp.employer join person pers on pers.perid = emp.employee") -// .setResultSetMapping( "org-emp-person" ) -// .list(); assertEquals( l.size(), 1 ); s.delete(emp); @@ -182,6 +191,12 @@ assertTrue( result.contains( "IFA" ) ); assertTrue( result.contains( "JBoss" ) ); + result = s.getNamedQuery( "orgNamesOnly" ).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); + Map m = (Map) result.get(0); + assertEquals( 2, result.size() ); + assertEquals( 1, m.size() ); + assertTrue( m.containsKey("NAME") ); + t.commit(); s.close(); @@ -258,13 +273,41 @@ s = openSession(); t = s.beginTransaction(); + Query sqlQuery = s.getNamedQuery("EmploymentAndPerson"); + sqlQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + list = sqlQuery.list(); + assertEquals(1,list.size() ); + Object res = list.get(0); + assertClassAssignability(res.getClass(),Map.class); + Map m = (Map) res; + assertEquals(2,m.size()); + t.commit(); + s.close(); + + s = openSession(); + t = s.beginTransaction(); + sqlQuery = s.getNamedQuery("organizationreturnproperty"); + sqlQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + list = sqlQuery.list(); + assertEquals(2,list.size() ); + m = (Map) list.get(0); + assertTrue(m.containsKey("org")); + assertClassAssignability(m.get("org").getClass(), Organization.class); + assertTrue(m.containsKey("emp")); + assertClassAssignability(m.get("emp").getClass(), Employment.class); + assertEquals(2, m.size()); + t.commit(); + s.close(); + + s = openSession(); + t = s.beginTransaction(); namedQuery = s.getNamedQuery("EmploymentAndPerson"); list = namedQuery.list(); assertEquals(1,list.size() ); Object[] objs = (Object[]) list.get(0); assertEquals(2, objs.length); emp2 = (Employment) objs[0]; - gavin = (Person) objs[1]; + gavin = (Person) objs[1]; s.delete(emp2); s.delete(jboss); s.delete(gavin); @@ -292,8 +335,6 @@ List list = s.createSQLQuery( getEmploymentSQL() ) .addEntity( Employment.class.getName() ) .list(); -// Query namedQuery = s.createSQLQuery("SELECT * FROM EMPLOYMENT").addEntity( Employment.class.getName() ); -// List list = namedQuery.list(); assertEquals( 1,list.size() ); Employment emp2 = (Employment) list.get(0); @@ -303,6 +344,28 @@ s.clear(); + list = s.createSQLQuery( getEmploymentSQL() ) + .addEntity( Employment.class.getName() ) + .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP) + .list(); + assertEquals( 1,list.size() ); + Map m = (Map) list.get(0); + assertTrue(m.containsKey("Employment")); + assertEquals(1,m.size()); + + list = s.createSQLQuery(getEmploymentSQL()).list(); + assertEquals(1, list.size()); + Object[] o = (Object[]) list.get(0); + assertEquals(8, o.length); + + list = s.createSQLQuery(getEmploymentSQL()).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); + assertEquals(1, list.size()); + m = (Map) list.get(0); + assertTrue(m.containsKey("EMPID")); + assertTrue(m.containsKey("VALUE")); + assertTrue(m.containsKey("ENDDATE")); + assertEquals(8, m.size()); + Query queryWithCollection = s.getNamedQuery("organizationEmploymentsExplicitAliases"); queryWithCollection.setLong("id", jboss.getId() ); list = queryWithCollection.list(); @@ -314,12 +377,6 @@ .addEntity( "org", Organization.class ) .addJoin( "emp", "org.employments" ) .list(); -// Query queryWithJoin = s.createSQLQuery( -// "SELECT org.orgid as {org.id}, org.name as {org.name}, {emp.*} FROM ORGANIZATION org LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER ") -// .addEntity("org", Organization.class).addJoin("emp", "org.employments"); -// -// queryWithJoin.list(); -// list = queryWithJoin.list(); assertEquals( 2,list.size() ); s.clear(); @@ -328,20 +385,6 @@ .addEntity( "org", Organization.class ) .addJoin( "emp", "org.employments" ) .list(); -// queryWithJoin = s.createSQLQuery( -// "SELECT org.orgid as {org.id}, org.name as {org.name}, emp.employer as {emp.key}, emp.empid as {emp.element}, {emp.element.*} FROM ORGANIZATION org LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER ") -// .addEntity("org", Organization.class).addJoin("emp", "org.employments"); -// -// list = queryWithJoin.list(); -// assertEquals( 2,list.size() ); -// -// s.clear(); -// -// queryWithJoin = s.createSQLQuery( -// "SELECT org.orgid as {org.id}, org.name as {org.name}, emp.employer as {emp.key}, emp.empid as {emp.element}, {emp.element.*} FROM ORGANIZATION org LEFT OUTER JOIN EMPLOYMENT emp ON org.ORGID = emp.EMPLOYER ") -// .addEntity("org", Organization.class).addJoin("emp", "org.employments"); -// -// list = queryWithJoin.list(); assertEquals( 2,list.size() ); s.clear(); @@ -349,19 +392,11 @@ // TODO : why twice? s.getNamedQuery( "organizationreturnproperty" ).list(); list = s.getNamedQuery( "organizationreturnproperty" ).list(); -// queryWithJoin = s.getNamedQuery("organizationreturnproperty"); -// queryWithJoin.list(); -// -// list = queryWithJoin.list(); assertEquals( 2,list.size() ); s.clear(); list = s.getNamedQuery( "organizationautodetect" ).list(); -// queryWithJoin = s.getNamedQuery("organizationautodetect"); -// queryWithJoin.list(); -// -// list = queryWithJoin.list(); assertEquals( 2,list.size() ); t.commit(); @@ -379,6 +414,8 @@ } + public static Test suite() { + return new TestSuite(GeneralTest.class); + } - } |