Author: stliu
Date: 2010-11-29 02:23:24 -0500 (Mon, 29 Nov 2010)
New Revision: 20872
Added:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasedTupleSubsetResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/CacheableResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/TupleSubsetResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/AbstractQueryCacheResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Address.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Course.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeeting.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeetingId.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheIgnoreResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheNormalResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCachePutResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.hbm.xml
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheIgnoreResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheNormalResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCachePutResultTransformerTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Student.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/StudentDTO.java
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/QueryKey.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/StandardQueryCache.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/dialect/HSQLDialect.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/HolderInstantiator.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/Loader.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/Getter.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanConstructorResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/ToListResultTransformer.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/CompositeUserType.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/EnhancedUserType.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/LoggableUserType.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserCollectionType.java
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserType.java
core/branches/Branch_3_3_2_GA_CP/core/src/test/java/org/hibernate/cache/QueryKeyTest.java
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java
Log:
JBPAPP-4175 JBPAPP-5478 JBPAPP-5479 HHH-5163 HHH-4011 HHH-2510 a big back port to fix the
bug of applying a resultTransformer on a chchable projection based criteria
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/QueryKey.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/QueryKey.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/QueryKey.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -34,7 +34,7 @@
import org.hibernate.engine.RowSelection;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.TypedValue;
-import org.hibernate.transform.ResultTransformer;
+import org.hibernate.transform.CacheableResultTransformer;
import org.hibernate.type.Type;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.EqualsHelper;
@@ -58,7 +58,7 @@
// the user provided resulttransformer, not the one used with "select new".
Here to avoid mangling
// transformed/non-transformed results.
- private final ResultTransformer customTransformer;
+ private final CacheableResultTransformer customTransformer;
/**
* For performance reasons, the hashCode is cached; however, it is marked transient so
that it can be
@@ -80,7 +80,8 @@
String queryString,
QueryParameters queryParameters,
Set filterKeys,
- SessionImplementor session) {
+ SessionImplementor session,
+ CacheableResultTransformer customTransformer) {
// disassemble positional parameters
final int positionalParameterCount =
queryParameters.getPositionalParameterTypes().length;
final Type[] types = new Type[positionalParameterCount];
@@ -134,7 +135,7 @@
maxRows,
filterKeys,
session.getEntityMode(),
- queryParameters.getResultTransformer()
+ customTransformer
);
}
@@ -160,7 +161,7 @@
Integer maxRows,
Set filterKeys,
EntityMode entityMode,
- ResultTransformer customTransformer) {
+ CacheableResultTransformer customTransformer) {
this.sqlQueryString = sqlQueryString;
this.positionalParameterTypes = positionalParameterTypes;
this.positionalParameterValues = positionalParameterValues;
@@ -172,6 +173,10 @@
this.customTransformer = customTransformer;
this.hashCode = generateHashCode();
}
+
+ public CacheableResultTransformer getResultTransformer() {
+ return customTransformer;
+ }
/**
* Deserialization hook used to re-init the cached hashcode which is needed for proper
clustering support.
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/StandardQueryCache.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/StandardQueryCache.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/cache/StandardQueryCache.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -94,6 +94,9 @@
}
List cacheable = new ArrayList( result.size() + 1 );
+ if ( log.isTraceEnabled() ) {
+ logCachedResultDetails( key, null, returnTypes, cacheable );
+ }
cacheable.add( ts );
for ( int i = 0; i < result.size(); i++ ) {
if ( returnTypes.length == 1 ) {
@@ -106,6 +109,9 @@
)
);
}
+ if ( log.isTraceEnabled() ) {
+ logCachedResultRowDetails( returnTypes, result.get( i ) );
+ }
}
cacheRegion.put( key, cacheable );
@@ -127,6 +133,10 @@
}
List cacheable = ( List ) cacheRegion.get( key );
+ if ( log.isTraceEnabled() ) {
+ logCachedResultDetails( key, spaces, returnTypes, cacheable );
+ }
+
if ( cacheable == null ) {
log.debug( "query results were not found in cache" );
return null;
@@ -160,6 +170,9 @@
)
);
}
+ if ( log.isTraceEnabled() ) {
+ logCachedResultRowDetails( returnTypes, result.get( i - 1 ));
+ }
}
catch ( UnresolvableObjectException uoe ) {
if ( isNaturalKeyLookup ) {
@@ -202,5 +215,72 @@
public String toString() {
return "StandardQueryCache(" + cacheRegion.getName() + ')';
}
+
+ private static void logCachedResultDetails(QueryKey key, Set querySpaces, Type[]
returnTypes, List result) {
+ if ( ! log.isTraceEnabled() ) {
+ return;
+ }
+ log.trace( "key.hashCode="+key.hashCode() );
+ log.trace( "querySpaces="+querySpaces );
+ if ( returnTypes == null || returnTypes.length == 0 ) {
+ log.trace( "unexpected returnTypes is "+( returnTypes == null ?
"null" : "empty" )+
+ "! result"+( result == null ? " is null": ".size()="
+ result.size() ) );
+ }
+ else {
+ StringBuffer returnTypeInfo = new StringBuffer();
+ for ( int i=0; i<returnTypes.length; i++ ) {
+ returnTypeInfo.append( "typename=" )
+ .append( returnTypes[ i ].getName() )
+ .append(" class=" )
+ .append( returnTypes[ i ].getReturnedClass().getName() ).append(' ');
+ }
+ log.trace( " returnTypeInfo="+returnTypeInfo );
+ }
+ }
+ private static void logCachedResultRowDetails(Type[] returnTypes, Object result) {
+ if ( ! log.isTraceEnabled() ) {
+ return;
+ }
+ logCachedResultRowDetails(
+ returnTypes,
+ ( result instanceof Object[] ? ( Object[] ) result : new Object[] { result } )
+ );
+ }
+
+ private static void logCachedResultRowDetails(Type[] returnTypes, Object[] tuple) {
+ if ( ! log.isTraceEnabled() ) {
+ return;
+ }
+ if ( tuple == null ) {
+ log.trace( " tuple is null; returnTypes is "+( returnTypes == null ?
"null" : "Type["+returnTypes.length+"]" ) );
+ if ( returnTypes != null && returnTypes.length > 1 ) {
+ log.trace( "unexpected result tuple! "+
+ "tuple is null; should be Object["+returnTypes.length+"]!" );
+ }
+ }
+ else {
+ if ( returnTypes == null || returnTypes.length == 0 ) {
+ log.trace( "unexpected result tuple! "+
+ "tuple is non-null; returnTypes is "+( returnTypes == null ?
"null" : "empty" ) );
+ }
+ log.trace( " tuple is Object["+tuple.length+
+ "]; returnTypes is Type["+returnTypes.length+"]" );
+ if ( tuple.length != returnTypes.length ) {
+ log.trace( "unexpected tuple length! transformer="+
+ " expected="+returnTypes.length+
+ " got="+tuple.length );
+ }
+ else {
+ for ( int j = 0; j < tuple.length; j++ ) {
+ if ( tuple[ j ] != null && ! returnTypes[ j ].getReturnedClass().isInstance(
tuple[ j ] ) ) {
+ log.trace( "unexpected tuple value type! transformer="+
+ " expected="+returnTypes[ j ].getReturnedClass().getName()+
+ " got="+tuple[ j ].getClass().getName() );
+ }
+ }
+ }
+ }
+ }
+
}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/dialect/HSQLDialect.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/dialect/HSQLDialect.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/dialect/HSQLDialect.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -172,7 +172,7 @@
public String getIdentityInsertString() {
return "null";
}
-
+
public String getForUpdateString() {
return "";
}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/HolderInstantiator.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/HolderInstantiator.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/HolderInstantiator.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -41,13 +41,16 @@
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);
- }
+ return new HolderInstantiator(
+ resolveResultTransformer( selectNewTransformer, customTransformer ),
+ queryReturnAliases
+ );
}
+ public static ResultTransformer resolveResultTransformer(ResultTransformer
selectNewTransformer, ResultTransformer customTransformer) {
+ return selectNewTransformer != null ? selectNewTransformer : customTransformer;
+ }
+
public static ResultTransformer createSelectNewTransformer(Constructor constructor,
boolean returnMaps, boolean returnLists) {
if ( constructor != null ) {
return new AliasToBeanConstructorResultTransformer(constructor);
@@ -65,13 +68,14 @@
static public HolderInstantiator createClassicHolderInstantiator(Constructor
constructor,
ResultTransformer transformer) {
- if ( constructor != null ) {
- return new HolderInstantiator(new
AliasToBeanConstructorResultTransformer(constructor), null);
- }
- else {
- return new HolderInstantiator(transformer, null);
- }
+ return new HolderInstantiator( resolveClassicResultTransformer( constructor,
transformer ), null );
}
+
+ static public ResultTransformer resolveClassicResultTransformer(
+ Constructor constructor,
+ ResultTransformer transformer) {
+ return constructor != null ? new AliasToBeanConstructorResultTransformer( constructor )
: transformer;
+ }
public HolderInstantiator(
ResultTransformer transformer,
@@ -86,11 +90,7 @@
}
public Object instantiate(Object[] row) {
- if(transformer==null) {
- return row;
- } else {
- return transformer.transformTuple(row, queryReturnAliases);
- }
+ return transformer == null ? row : transformer.transformTuple(row,
queryReturnAliases);
}
public String[] getQueryReturnAliases() {
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/hql/classic/QueryTranslatorImpl.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -30,6 +30,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -977,29 +978,25 @@
throw new UnsupportedOperationException( "Not supported! Use the AST
translator...");
}
- protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer,
ResultSet rs, SessionImplementor session)
+ protected Object getResultColumnOrRow( Object[] row, ResultTransformer transformer,
ResultSet rs, SessionImplementor session )
throws SQLException, HibernateException {
- row = toResultRow( row );
+ Object[] resultRow = getResultRow( row, rs, session );
+ return (holderClass == null && resultRow.length == 1 ? resultRow[0] :
resultRow);
+ }
+
+ protected Object[] getResultRow( Object[] row, ResultSet rs, SessionImplementor session
) throws SQLException, HibernateException {
+ Object[] resultRow;
if ( hasScalars ) {
String[][] scalarColumns = getColumnNames();
int queryCols = returnTypes.length;
- if ( holderClass == null && queryCols == 1 ) {
- return returnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null );
+ resultRow = new Object[queryCols];
+ for ( int i = 0; i < queryCols; i++ ) {
+ resultRow[i] = returnTypes[i].nullSafeGet( rs, scalarColumns[i], 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 {
+ resultRow = toResultRow( row );
}
- else if ( holderClass == null ) {
- return row.length == 1 ? row[0] : row;
- }
- else {
- return row;
- }
-
+ return resultRow;
}
protected List getResultList(List results, ResultTransformer resultTransformer) throws
QueryException {
@@ -1030,6 +1027,20 @@
return result;
}
}
+ protected boolean[] includeInResultRow() {
+ boolean[] isResultReturned = includeInSelect;
+ if ( hasScalars ) {
+ isResultReturned = new boolean[ returnedTypes.size() ];
+ Arrays.fill( isResultReturned, true );
+ }
+ return isResultReturned;
+ }
+ protected ResultTransformer resolveResultTransformer(ResultTransformer
resultTransformer) {
+ return HolderInstantiator.resolveClassicResultTransformer(
+ holderConstructor,
+ resultTransformer
+ );
+ }
void setHolderClass(Class clazz) {
holderClass = clazz;
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/Loader.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/Loader.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/Loader.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -75,6 +75,7 @@
import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.transform.CacheableResultTransformer;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
@@ -172,6 +173,10 @@
protected int[] getCollectionOwners() {
return null;
}
+
+ protected int[][] getCompositeKeyManyToOneTargetIndices() {
+ return null;
+ }
/**
* What lock mode does this load entities with?
@@ -241,21 +246,56 @@
}
}
+// /**
+// * Execute an SQL query and attempt to instantiate instances of the class mapped by
the given
+// * persister from each row of the <tt>ResultSet</tt>. If an object is
supplied, will attempt to
+// * initialize that object. If a collection is supplied, attempt to initialize that
collection.
+// */
+// private List doQueryAndInitializeNonLazyCollections(final SessionImplementor session,
+// final QueryParameters queryParameters,
+// final boolean returnProxies)
+// throws HibernateException, SQLException {
+//
+// final PersistenceContext persistenceContext = session.getPersistenceContext();
+// persistenceContext.beforeLoad();
+// List result;
+// try {
+// result = doQuery( session, queryParameters, returnProxies );
+// }
+// finally {
+// persistenceContext.afterLoad();
+// }
+// persistenceContext.initializeNonLazyCollections();
+// return result;
+// }
/**
* Execute an SQL query and attempt to instantiate instances of the class mapped by the
given
* persister from each row of the <tt>ResultSet</tt>. If an object is
supplied, will attempt to
* initialize that object. If a collection is supplied, attempt to initialize that
collection.
*/
- private List doQueryAndInitializeNonLazyCollections(final SessionImplementor session,
- final QueryParameters queryParameters,
- final boolean returnProxies)
- throws HibernateException, SQLException {
+ private List doQueryAndInitializeNonLazyCollections(
+ final SessionImplementor session,
+ final QueryParameters queryParameters,
+ final boolean returnProxies) throws HibernateException, SQLException {
+ return doQueryAndInitializeNonLazyCollections(
+ session,
+ queryParameters,
+ returnProxies,
+ null
+ );
+ }
+ private List doQueryAndInitializeNonLazyCollections(
+ final SessionImplementor session,
+ final QueryParameters queryParameters,
+ final boolean returnProxies,
+ final ResultTransformer forcedResultTransformer)
+ throws HibernateException, SQLException {
final PersistenceContext persistenceContext = session.getPersistenceContext();
persistenceContext.beforeLoad();
List result;
try {
- result = doQuery( session, queryParameters, returnProxies );
+ result = doQuery( session, queryParameters, returnProxies, forcedResultTransformer );
}
finally {
persistenceContext.afterLoad();
@@ -569,7 +609,6 @@
}
}
-
private Object getRowFromResultSet(
final ResultSet resultSet,
final SessionImplementor session,
@@ -579,23 +618,23 @@
final List hydratedObjects,
final EntityKey[] keys,
boolean returnProxies) throws SQLException, HibernateException {
+ return getRowFromResultSet( resultSet, session, queryParameters, lockModeArray,
optionalObjectKey, hydratedObjects, keys, returnProxies, null );
+
+ }
+ private Object getRowFromResultSet(
+ final ResultSet resultSet,
+ final SessionImplementor session,
+ final QueryParameters queryParameters,
+ final LockMode[] lockModeArray,
+ final EntityKey optionalObjectKey,
+ final List hydratedObjects,
+ final EntityKey[] keys,
+ boolean returnProxies,
+ ResultTransformer forcedResultTransformer) throws SQLException,
HibernateException {
final Loadable[] persisters = getEntityPersisters();
final int entitySpan = persisters.length;
-
- for ( int i = 0; i < entitySpan; i++ ) {
- keys[i] = getKeyFromResultSet(
- i,
- persisters[i],
- i == entitySpan - 1 ?
- queryParameters.getOptionalId() :
- null,
- resultSet,
- session
- );
- //TODO: the i==entitySpan-1 bit depends upon subclass implementation (very bad)
- }
-
+ extractKeysFromResultSet( persisters, queryParameters, resultSet, session, keys,
lockModeArray, hydratedObjects );
registerNonExists( keys, persisters, session );
// this call is side-effecty
@@ -625,10 +664,112 @@
}
}
- return getResultColumnOrRow( row, queryParameters.getResultTransformer(), resultSet,
session );
+ return forcedResultTransformer == null ?
+ getResultColumnOrRow( row, queryParameters.getResultTransformer(), resultSet, session
) :
+ forcedResultTransformer.transformTuple(
+ getResultRow( row, resultSet, session ),
+ getResultRowAliases()
+ )
+ ;
}
+ protected Object[] getResultRow( Object[] row, ResultSet rs, SessionImplementor session
) throws SQLException, HibernateException {
+ return row;
+ }
+
+ protected void extractKeysFromResultSet(
+ Loadable[] persisters,
+ QueryParameters queryParameters,
+ ResultSet resultSet,
+ SessionImplementor session,
+ EntityKey[] keys,
+ LockMode[] lockModes,
+ List hydratedObjects) throws SQLException {
+ final int entitySpan = persisters.length;
+
+ final int numberOfPersistersToProcess;
+ final Serializable optionalId = queryParameters.getOptionalId();
+ if ( isSingleRowLoader() && optionalId != null ) {
+ keys[ entitySpan - 1 ] = new EntityKey( optionalId, persisters[ entitySpan - 1 ],
session.getEntityMode() );
+ // skip the last persister below...
+ numberOfPersistersToProcess = entitySpan - 1;
+ }
+ else {
+ numberOfPersistersToProcess = entitySpan;
+ }
+
+ final Object[] hydratedKeyState = new Object[numberOfPersistersToProcess];
+
+ for ( int i = 0; i < numberOfPersistersToProcess; i++ ) {
+ final Type idType = persisters[i].getIdentifierType();
+ hydratedKeyState[i] = idType.hydrate( resultSet,
getEntityAliases()[i].getSuffixedKeyAliases(), session, null );
+ }
+
+ for ( int i = 0; i < numberOfPersistersToProcess; i++ ) {
+ final Type idType = persisters[i].getIdentifierType();
+ if ( idType.isComponentType() && getCompositeKeyManyToOneTargetIndices() !=
null ) {
+ // we may need to force resolve any key-many-to-one(s)
+ int[] keyManyToOneTargetIndices = getCompositeKeyManyToOneTargetIndices()[i];
+ // todo : better solution is to order the index processing based on target indices
+ // that would account for multiple levels whereas this scheme does not
+ if ( keyManyToOneTargetIndices != null ) {
+ for ( int targetIndex : keyManyToOneTargetIndices ) {
+ if ( targetIndex < numberOfPersistersToProcess ) {
+ final Type targetIdType = persisters[targetIndex].getIdentifierType();
+ final Serializable targetId = (Serializable) targetIdType.resolve(
+ hydratedKeyState[targetIndex],
+ session,
+ null
+ );
+ // todo : need a way to signal that this key is resolved and its data resolved
+ keys[targetIndex] = new EntityKey( targetId, persisters[targetIndex],
session.getEntityMode() );
+ }
+
+ // this part copied from #getRow, this section could be refactored out
+ Object object = session.getEntityUsingInterceptor( keys[targetIndex] );
+ if ( object != null ) {
+ //its already loaded so don't need to hydrate it
+ instanceAlreadyLoaded(
+ resultSet,
+ targetIndex,
+ persisters[targetIndex],
+ keys[targetIndex],
+ object,
+ lockModes[targetIndex],
+ session
+ );
+ }
+ else {
+ object = instanceNotYetLoaded(
+ resultSet,
+ targetIndex,
+ persisters[targetIndex],
+ getEntityAliases()[targetIndex].getRowIdAlias(),
+ keys[targetIndex],
+ lockModes[targetIndex],
+ getOptionalObjectKey( queryParameters, session ),
+ queryParameters.getOptionalObject(),
+ hydratedObjects,
+ session
+ );
+ }
+ }
+ }
+ }
+ final Serializable resolvedId = (Serializable) idType.resolve( hydratedKeyState[i],
session, null );
+ keys[i] = resolvedId == null ? null : new EntityKey( resolvedId, persisters[i],
session.getEntityMode() );
+ }
+ }
+
+ private Serializable determineResultId(SessionImplementor session, Serializable
optionalId, Type idType, Serializable resolvedId) {
+ final boolean idIsResultId = optionalId != null
+ && resolvedId != null
+ && idType.isEqual( optionalId, resolvedId, session.getEntityMode(), factory
);
+ final Serializable resultId = idIsResultId ? optionalId : resolvedId;
+ return resultId;
+ }
+
/**
* Read any collection elements contained in a single row of the result set
*/
@@ -682,7 +823,8 @@
private List doQuery(
final SessionImplementor session,
final QueryParameters queryParameters,
- final boolean returnProxies) throws SQLException, HibernateException {
+ final boolean returnProxies,
+ final ResultTransformer forcedResultTransformer) throws SQLException,
HibernateException {
final RowSelection selection = queryParameters.getRowSelection();
final int maxRows = hasMaxRows( selection ) ?
@@ -728,7 +870,8 @@
optionalObjectKey,
hydratedObjects,
keys,
- returnProxies
+ returnProxies,
+ forcedResultTransformer
);
results.add( result );
@@ -902,11 +1045,42 @@
.endLoadingCollections( collectionPersister );
}
+ /**
+ * Determine the actual ResultTransformer that will be used to
+ * transform query results.
+ *
+ * @param resultTransformer the specified result transformer
+ * @return the actual result transformer
+ */
+ protected ResultTransformer resolveResultTransformer(ResultTransformer
resultTransformer) {
+ return resultTransformer;
+ }
+
protected List getResultList(List results, ResultTransformer resultTransformer) throws
QueryException {
return results;
}
/**
+ * Are rows transformed immediately after being read from the ResultSet?
+ * @return true, if getResultColumnOrRow() transforms the results; false, otherwise
+ */
+ protected boolean areResultSetRowsTransformedImmediately() {
+ return false;
+ }
+
+ /**
+ * Returns the aliases that corresponding to a result row.
+ * @return Returns the aliases that corresponding to a result row.
+ */
+ protected String[] getResultRowAliases() {
+ return null;
+ }
+
+ protected boolean[] includeInResultRow() {
+ return null;
+ }
+
+ /**
* Get the actual object that is returned in the user-visible result list.
* This empty implementation merely returns its first argument. This is
* overridden by some subclasses.
@@ -2138,17 +2312,15 @@
QueryCache queryCache = factory.getQueryCache( queryParameters.getCacheRegion() );
- Set filterKeys = FilterKey.createFilterKeys(
- session.getEnabledFilters(),
- session.getEntityMode()
- );
- QueryKey key = QueryKey.generateQueryKey(
- getSQLString(),
- queryParameters,
- filterKeys,
- session
- );
+ QueryKey key = generateQueryKey( session, queryParameters );
+ if ( querySpaces == null || querySpaces.size() == 0 ) {
+ log.trace( "unexpected querySpaces is "+( querySpaces == null ?
"null" : "empty" ) );
+ }
+ else {
+ log.trace( "querySpaces is "+querySpaces.toString() );
+ }
+
List result = getResultFromQueryCache(
session,
queryParameters,
@@ -2159,7 +2331,7 @@
);
if ( result == null ) {
- result = doList( session, queryParameters );
+ result = doList( session, queryParameters, key.getResultTransformer() );
putResultInQueryCache(
session,
@@ -2170,10 +2342,49 @@
result
);
}
+
+ ResultTransformer resolvedTransformer = resolveResultTransformer(
queryParameters.getResultTransformer() );
+ if ( resolvedTransformer != null ) {
+ result = (
+ areResultSetRowsTransformedImmediately() ?
+ key.getResultTransformer().retransformResults(
+ result,
+ getResultRowAliases(),
+ queryParameters.getResultTransformer(),
+ includeInResultRow()
+ ) :
+ key.getResultTransformer().untransformToTuples(
+ result
+ )
+ );
+ }
return getResultList( result, queryParameters.getResultTransformer() );
}
+
+ private QueryKey generateQueryKey(
+ SessionImplementor session,
+ QueryParameters queryParameters) {
+ return QueryKey.generateQueryKey(
+ getSQLString(),
+ queryParameters,
+ FilterKey.createFilterKeys(
+ session.getEnabledFilters(),
+ session.getEntityMode()
+ ),
+ session,
+ createCacheableResultTransformer( queryParameters )
+ );
+ }
+ private CacheableResultTransformer createCacheableResultTransformer(QueryParameters
queryParameters) {
+ return CacheableResultTransformer.create(
+ queryParameters.getResultTransformer(),
+ getResultRowAliases(),
+ includeInResultRow()
+ );
+ }
+
private List getResultFromQueryCache(
final SessionImplementor session,
final QueryParameters queryParameters,
@@ -2186,7 +2397,7 @@
if ( session.getCacheMode().isGetEnabled() ) {
boolean isImmutableNaturalKeyLookup = queryParameters.isNaturalKeyLookup()
&& getEntityPersisters()[0].getEntityMetamodel().hasImmutableNaturalId();
- result = queryCache.get( key, resultTypes, isImmutableNaturalKeyLookup, querySpaces,
session );
+ result = queryCache.get( key, key.getResultTransformer().getCachedResultTypes(
resultTypes ), isImmutableNaturalKeyLookup, querySpaces, session );
if ( factory.getStatistics().isStatisticsEnabled() ) {
if ( result == null ) {
factory.getStatisticsImplementor()
@@ -2202,26 +2413,25 @@
return result;
}
- private void putResultInQueryCache(
- final SessionImplementor session,
- final QueryParameters queryParameters,
- final Type[] resultTypes,
- final QueryCache queryCache,
- final QueryKey key,
- final List result) {
+ private void putResultInQueryCache( final SessionImplementor session, final
QueryParameters queryParameters, final Type[] resultTypes,
+ final QueryCache queryCache, final QueryKey key, final List result ) {
if ( session.getCacheMode().isPutEnabled() ) {
- boolean put = queryCache.put( key, resultTypes, result,
queryParameters.isNaturalKeyLookup(), session );
+ boolean put = queryCache.put( key, key.getResultTransformer().getCachedResultTypes(
resultTypes ), result,
+ queryParameters.isNaturalKeyLookup(), session );
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
- factory.getStatisticsImplementor()
- .queryCachePut( getQueryIdentifier(), queryCache.getRegion().getName() );
+ factory.getStatisticsImplementor().queryCachePut( getQueryIdentifier(),
queryCache.getRegion().getName() );
}
}
}
+ protected List doList( final SessionImplementor session, final QueryParameters
queryParameters ) throws HibernateException {
+ return doList( session, queryParameters, null );
+ }
+
/**
* Actually execute a query, ignoring the query cache
*/
- protected List doList(final SessionImplementor session, final QueryParameters
queryParameters)
+ protected List doList(final SessionImplementor session, final QueryParameters
queryParameters, final ResultTransformer forcedResultTransformer)
throws HibernateException {
final boolean stats = getFactory().getStatistics().isStatisticsEnabled();
@@ -2230,7 +2440,7 @@
List result;
try {
- result = doQueryAndInitializeNonLazyCollections( session, queryParameters, true );
+ result = doQueryAndInitializeNonLazyCollections( session, queryParameters, true,
forcedResultTransformer );
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaJoinWalker.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -25,6 +25,7 @@
package org.hibernate.loader.criteria;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -59,10 +60,13 @@
private final CriteriaQueryTranslator translator;
private final Set querySpaces;
private final Type[] resultTypes;
+ private final boolean[] includeInResultRow;
//the user visible aliases, which are unknown to the superclass,
//these are not the actual "physical" SQL aliases
private final String[] userAliases;
private final List userAliasList = new ArrayList();
+ private final List resultTypeList = new ArrayList();
+ private final List includeInResultRowList = new ArrayList();
public Type[] getResultTypes() {
return resultTypes;
@@ -71,6 +75,10 @@
public String[] getUserAliases() {
return userAliases;
}
+
+ public boolean[] includeInResultRow() {
+ return includeInResultRow;
+ }
public CriteriaJoinWalker(
final OuterJoinLoadable persister,
@@ -97,8 +105,6 @@
querySpaces = translator.getQuerySpaces();
if ( translator.hasProjection() ) {
- resultTypes = translator.getProjectedTypes();
-
initProjection(
translator.getSelect(),
translator.getWhereCondition(),
@@ -106,16 +112,22 @@
translator.getGroupBy(),
LockMode.NONE
);
+ resultTypes = translator.getProjectedTypes();
+ userAliases = translator.getProjectedAliases();
+ includeInResultRow = new boolean[ resultTypes.length ];
+ Arrays.fill( includeInResultRow, true );
}
else {
- resultTypes = new Type[] { TypeFactory.manyToOne( persister.getEntityName() ) };
-
initAll( translator.getWhereCondition(), translator.getOrderBy(), LockMode.NONE );
+ // root entity comes last
+ userAliasList.add( criteria.getAlias() ); //root entity comes *last*
+ resultTypeList.add( translator.getResultType( criteria ) );
+ includeInResultRowList.add( true );
+ userAliases = ArrayHelper.toStringArray( userAliasList );
+ resultTypes = ArrayHelper.toTypeArray( resultTypeList );
+ includeInResultRow = ArrayHelper.toBooleanArray( includeInResultRowList );
+
}
-
- userAliasList.add( criteria.getAlias() ); //root entity comes *last*
- userAliases = ArrayHelper.toStringArray(userAliasList);
-
}
protected int getJoinType(
@@ -180,11 +192,20 @@
final Criteria subcriteria = translator.getCriteria(path);
String sqlAlias = subcriteria==null ? null : translator.getSQLAlias(subcriteria);
if (sqlAlias!=null) {
- userAliasList.add( subcriteria.getAlias() ); //alias may be null
+// userAliasList.add( subcriteria.getAlias() ); //alias may be null
+ if( !translator.hasProjection() ){
+ includeInResultRowList.add( subcriteria.getAlias() != null );
+ if( subcriteria.getAlias() != null ){
+ userAliasList.add( subcriteria.getAlias() );
+ resultTypeList.add( translator.getResultType( subcriteria ) );
+ }
+ }
return sqlAlias; //EARLY EXIT
}
else {
- userAliasList.add(null);
+ if ( ! translator.hasProjection() ) {
+ includeInResultRowList.add( false );
+ }
}
}
return super.generateTableAlias( n + translator.getSQLAliasCount(), path, joinable );
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaLoader.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -46,6 +46,7 @@
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;
+import org.hibernate.util.ArrayHelper;
/**
* A <tt>Loader</tt> for <tt>Criteria</tt> queries. Note that
criteria queries are
@@ -68,6 +69,8 @@
//the user visible aliases, which are unknown to the superclass,
//these are not the actual "physical" SQL aliases
private final String[] userAliases;
+ private final boolean[] includeInResultRow;
+ private final int resultRowLength;
public CriteriaLoader(
final OuterJoinLoadable persister,
@@ -100,7 +103,8 @@
userAliases = walker.getUserAliases();
resultTypes = walker.getResultTypes();
-
+ includeInResultRow = walker.includeInResultRow();
+ resultRowLength = ArrayHelper.countTrue( includeInResultRow );
postInstantiate();
}
@@ -120,8 +124,15 @@
protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer,
ResultSet rs, SessionImplementor session)
throws SQLException, HibernateException {
+ return resolveResultTransformer( transformer ).transformTuple(
+ getResultRow( row, rs, session),
+ getResultRowAliases()
+ );
+ }
+
+ protected Object[] getResultRow(Object[] row, ResultSet rs, SessionImplementor session)
+ throws SQLException, HibernateException {
final Object[] result;
- final String[] aliases;
if ( translator.hasProjection() ) {
Type[] types = translator.getProjectedTypes();
result = new Object[types.length];
@@ -129,20 +140,45 @@
for ( int i=0; i<result.length; i++ ) {
result[i] = types[i].nullSafeGet(rs, columnAliases[i], session, null);
}
- aliases = translator.getProjectedAliases();
}
else {
- result = row;
- aliases = userAliases;
+ result = toResultRow( row );
}
- return translator.getRootCriteria().getResultTransformer()
- .transformTuple(result, aliases);
+ return result;
}
+ private Object[] toResultRow(Object[] row) {
+ if ( resultRowLength == row.length ) {
+ return row;
+ }
+ else {
+ Object[] result = new Object[ resultRowLength ];
+ int j = 0;
+ for ( int i = 0; i < row.length; i++ ) {
+ if ( includeInResultRow[i] ) result[j++] = row[i];
+ }
+ return result;
+ }
+ }
+
public Set getQuerySpaces() {
return querySpaces;
}
+
+ protected String[] getResultRowAliases() {
+ return userAliases;
+ }
+
+ protected ResultTransformer resolveResultTransformer(ResultTransformer
resultTransformer) {
+ return translator.getRootCriteria().getResultTransformer();
+ }
+ protected boolean areResultSetRowsTransformedImmediately() {
+ return true;
+ }
+ protected boolean[] includeInResultRow() {
+ return includeInResultRow;
+ }
protected String applyLocks(String sqlSelectString, Map lockModes, Dialect dialect)
throws QueryException {
if ( lockModes == null || lockModes.isEmpty() ) {
return sqlSelectString;
@@ -184,7 +220,7 @@
}
protected List getResultList(List results, ResultTransformer resultTransformer) {
- return translator.getRootCriteria().getResultTransformer().transformList( results );
+ return resolveResultTransformer( resultTransformer ).transformList( results );
}
}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/criteria/CriteriaQueryTranslator.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -55,6 +55,7 @@
import org.hibernate.type.AssociationType;
import org.hibernate.type.NullableType;
import org.hibernate.type.Type;
+import org.hibernate.type.TypeFactory;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.StringHelper;
@@ -336,6 +337,11 @@
this
);
}
+
+ /* package-protected */
+ Type getResultType(Criteria criteria) {
+ return TypeFactory.manyToOne( getEntityName( criteria ) );
+ }
public Type[] getProjectedTypes() {
return rootCriteria.getProjection().getTypes( rootCriteria, this );
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/custom/CustomLoader.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -79,6 +79,7 @@
private final CollectionAliases[] collectionAliases;
private final LockMode[] lockModes;
+ private boolean[] includeInResultRow;
// private final String[] sqlAliases;
// private final String[] sqlAliasSuffixes;
private final ResultRowProcessor rowProcessor;
@@ -113,7 +114,9 @@
List specifiedAliases = new ArrayList();
int returnableCounter = 0;
boolean hasScalars = false;
-
+
+ List includeInResultRowList = new ArrayList();
+
Iterator itr = customQuery.getCustomQueryReturns().iterator();
while ( itr.hasNext() ) {
final Return rtn = ( Return ) itr.next();
@@ -127,6 +130,7 @@
scalarRtn.getType()
)
);
+ includeInResultRowList.add( true );
hasScalars = true;
}
else if ( rtn instanceof RootReturn ) {
@@ -141,6 +145,7 @@
specifiedAliases.add( rootRtn.getAlias() );
entityAliases.add( rootRtn.getEntityAliases() );
ArrayHelper.addAll( querySpaces, persister.getQuerySpaces() );
+ includeInResultRowList.add( true );
}
else if ( rtn instanceof CollectionReturn ) {
CollectionReturn collRtn = ( CollectionReturn ) rtn;
@@ -163,6 +168,7 @@
entityAliases.add( collRtn.getElementEntityAliases() );
ArrayHelper.addAll( querySpaces, elementPersister.getQuerySpaces() );
}
+ includeInResultRowList.add( true );
}
else if ( rtn instanceof EntityFetchReturn ) {
EntityFetchReturn fetchRtn = ( EntityFetchReturn ) rtn;
@@ -179,6 +185,7 @@
specifiedAliases.add( fetchRtn.getAlias() );
entityAliases.add( fetchRtn.getEntityAliases() );
ArrayHelper.addAll( querySpaces, persister.getQuerySpaces() );
+ includeInResultRowList.add( false );
}
else if ( rtn instanceof CollectionFetchReturn ) {
CollectionFetchReturn fetchRtn = ( CollectionFetchReturn ) rtn;
@@ -202,6 +209,7 @@
entityAliases.add( fetchRtn.getElementEntityAliases() );
ArrayHelper.addAll( querySpaces, elementPersister.getQuerySpaces() );
}
+ includeInResultRowList.add( false );
}
else {
throw new HibernateException( "unexpected custom query return type : " +
rtn.getClass().getName() );
@@ -240,6 +248,7 @@
hasScalars,
( ResultColumnProcessor[] ) resultColumnProcessors.toArray( new
ResultColumnProcessor[ resultColumnProcessors.size() ] )
);
+ this.includeInResultRow = ArrayHelper.toBooleanArray( includeInResultRowList );
}
private Queryable determineAppropriateOwnerPersister(NonScalarReturn ownerDescriptor) {
@@ -332,6 +341,18 @@
}
}
+ protected String[] getResultRowAliases(){
+ return transformerAliases;
+ }
+
+ protected ResultTransformer resolveResultTransformer(ResultTransformer
resultTransformer) {
+ return HolderInstantiator.resolveResultTransformer( null, resultTransformer );
+ }
+
+ protected boolean[] includeInResultRow(){
+ return includeInResultRow;
+ }
+
protected Object getResultColumnOrRow(
Object[] row,
ResultTransformer transformer,
@@ -340,6 +361,11 @@
return rowProcessor.buildResultRow( row, rs, transformer != null, session );
}
+ protected Object[] getResultRow( Object[] row, ResultSet rs, SessionImplementor session
)
+ throws SQLException, HibernateException{
+ return rowProcessor.buildResultRow( row, rs, session );
+ }
+
protected List getResultList(List results, ResultTransformer resultTransformer) throws
QueryException {
// meant to handle dynamic instantiation queries...(Copy from QueryLoader)
HolderInstantiator holderInstantiator = HolderInstantiator.getHolderInstantiator(
@@ -430,6 +456,17 @@
ResultSet resultSet,
boolean hasTransformer,
SessionImplementor session) throws SQLException, HibernateException {
+ Object[] resultRow = buildResultRow( data, resultSet, session );
+ return ( hasTransformer )
+ ? resultRow
+ : ( resultRow.length == 1 )
+ ? resultRow[0]
+ : resultRow;
+ }
+ public Object[] buildResultRow(
+ Object[] data,
+ ResultSet resultSet,
+ SessionImplementor session) throws SQLException, HibernateException {
Object[] resultRow;
if ( !hasScalars ) {
resultRow = data;
@@ -444,11 +481,7 @@
}
}
- return ( hasTransformer )
- ? resultRow
- : ( resultRow.length == 1 )
- ? resultRow[0]
- : resultRow;
+ return resultRow;
}
}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -27,6 +27,7 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -343,33 +344,45 @@
private boolean hasSelectNew() {
return selectNewTransformer!=null;
}
+
+ protected String[] getResultRowAliases() {
+ return queryReturnAliases;
+ }
+
+ protected ResultTransformer resolveResultTransformer(ResultTransformer
resultTransformer) {
+ return HolderInstantiator.resolveResultTransformer( selectNewTransformer,
resultTransformer );
+ }
+
+ protected boolean[] includeInResultRow() {
+ boolean[] includeInResultTuple = includeInSelect;
+ if ( hasScalars ) {
+ includeInResultTuple = new boolean[ queryReturnTypes.length ];
+ Arrays.fill( includeInResultTuple, true );
+ }
+ return includeInResultTuple;
+ }
- protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer,
ResultSet rs, SessionImplementor session)
+ protected Object getResultColumnOrRow( Object[] row, ResultTransformer transformer,
ResultSet rs, SessionImplementor session )
throws SQLException, HibernateException {
- row = toResultRow( row );
- boolean hasTransform = hasSelectNew() || transformer!=null;
+ Object[] resultRow = getResultRow( row, rs, session );
+ boolean hasTransform = hasSelectNew() || transformer != null;
+ return (!hasTransform && resultRow.length == 1 ? resultRow[0] : resultRow);
+ }
+
+ protected Object[] getResultRow( Object[] row, ResultSet rs, SessionImplementor session
) throws SQLException, HibernateException {
+ Object[] resultRow;
if ( hasScalars ) {
String[][] scalarColumns = scalarColumnNames;
int queryCols = queryReturnTypes.length;
- if ( !hasTransform && queryCols == 1 ) {
- return queryReturnTypes[0].nullSafeGet( rs, scalarColumns[0], session, null );
+ resultRow = new Object[queryCols];
+ for ( int i = 0; i < queryCols; i++ ) {
+ resultRow[i] = queryReturnTypes[i].nullSafeGet( rs, scalarColumns[i], 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 {
+ resultRow = toResultRow( row );
}
- else if ( !hasTransform ) {
- return row.length == 1 ? row[0] : row;
- }
- else {
- return row;
- }
-
+ return resultRow;
}
protected List getResultList(List results, ResultTransformer resultTransformer) throws
QueryException {
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/Getter.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/Getter.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/Getter.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -39,7 +39,7 @@
public interface Getter extends Serializable {
/**
* Get the property value from the given instance .
- * @param owner The instance containing the value to be retreived.
+ * @param owner The instance containing the value to be retrieved.
* @return The extracted value.
* @throws HibernateException
*/
@@ -48,7 +48,7 @@
/**
* Get the property value from the given owner instance.
*
- * @param owner The instance containing the value to be retreived.
+ * @param owner The instance containing the value to be retrieved.
* @param mergeMap a map of merged persistent instances to detached instances
* @param session The session from which this request originated.
* @return The extracted value.
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -87,7 +87,7 @@
throw new MappingException( "Unknown entity mode [" + mode +
"]" );
}
} /**
- * Retreives a PropertyAccessor specific for a PojoRepresentation with the given access
strategy.
+ * Retrieves a PropertyAccessor specific for a PojoRepresentation with the given access
strategy.
*
* @param pojoAccessorStrategy The access strategy.
* @return An appropriate accessor.
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanConstructorResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanConstructorResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanConstructorResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -41,7 +41,7 @@
/**
* Instantiates a AliasToBeanConstructorResultTransformer.
*
- * @param constructor The contructor in which to wrap the tuples.
+ * @param constructor The constructor in which to wrap the tuples.
*/
public AliasToBeanConstructorResultTransformer(Constructor constructor) {
this.constructor = constructor;
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToBeanResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -24,7 +24,7 @@
*/
package org.hibernate.transform;
-import java.util.List;
+import java.util.Arrays;
import org.hibernate.HibernateException;
import org.hibernate.property.ChainedPropertyAccessor;
@@ -52,42 +52,43 @@
*
* @author max
*/
-public class AliasToBeanResultTransformer implements ResultTransformer {
+public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransformer {
// IMPL NOTE : due to the delayed population of setters (setters cached
// for performance), we really cannot pro0perly define equality for
// this transformer
private final Class resultClass;
- private final PropertyAccessor propertyAccessor;
+ private boolean isInitialized;
+ private String[] aliases;
private Setter[] setters;
public AliasToBeanResultTransformer(Class resultClass) {
if ( resultClass == null ) {
throw new IllegalArgumentException( "resultClass cannot be null" );
}
+ this.isInitialized = false;
this.resultClass = resultClass;
- propertyAccessor = new ChainedPropertyAccessor(
- new PropertyAccessor[] {
- PropertyAccessorFactory.getPropertyAccessor( resultClass, null ),
- PropertyAccessorFactory.getPropertyAccessor( "field" )
- }
- );
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
+ return false;
+ }
public Object transformTuple(Object[] tuple, String[] aliases) {
Object result;
try {
- if ( setters == null ) {
- setters = new Setter[aliases.length];
- for ( int i = 0; i < aliases.length; i++ ) {
- String alias = aliases[i];
- if ( alias != null ) {
- setters[i] = propertyAccessor.getSetter( resultClass, alias );
- }
- }
+ if ( ! isInitialized ) {
+ initialize( aliases );
}
+ else {
+ check( aliases );
+ }
+
result = resultClass.newInstance();
for ( int i = 0; i < aliases.length; i++ ) {
@@ -106,14 +107,57 @@
return result;
}
- public List transformList(List collection) {
- return collection;
+ private void initialize(String[] aliases) {
+ PropertyAccessor propertyAccessor = new ChainedPropertyAccessor(
+ new PropertyAccessor[] {
+ PropertyAccessorFactory.getPropertyAccessor( resultClass, null ),
+ PropertyAccessorFactory.getPropertyAccessor( "field" )
+ }
+ );
+ this.aliases = new String[ aliases.length ];
+ setters = new Setter[ aliases.length ];
+ for ( int i = 0; i < aliases.length; i++ ) {
+ String alias = aliases[ i ];
+ if ( alias != null ) {
+ this.aliases[ i ] = alias;
+ setters[ i ] = propertyAccessor.getSetter( resultClass, alias );
+ }
+ }
+ isInitialized = true;
}
+
+ private void check(String[] aliases) {
+ if ( ! Arrays.equals( aliases, this.aliases ) ) {
+ throw new IllegalStateException(
+ "aliases are different from what is cached; aliases=" + Arrays.asList(
aliases ) +
+ " cached=" + Arrays.asList( this.aliases ) );
+ }
+ }
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ AliasToBeanResultTransformer that = ( AliasToBeanResultTransformer ) o;
+
+ if ( ! resultClass.equals( that.resultClass ) ) {
+ return false;
+ }
+ if ( ! Arrays.equals( aliases, that.aliases ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
public int hashCode() {
- int result;
- result = resultClass.hashCode();
- result = 31 * result + propertyAccessor.hashCode();
+ int result = resultClass.hashCode();
+ result = 31 * result + ( aliases != null ? Arrays.hashCode( aliases ) : 0 );
return result;
}
+
}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasToEntityMapResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -24,7 +24,6 @@
*/
package org.hibernate.transform;
-import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@@ -39,7 +38,7 @@
* @author Gavin King
* @author Steve Ebersole
*/
-public class AliasToEntityMapResultTransformer extends BasicTransformerAdapter implements
Serializable {
+public class AliasToEntityMapResultTransformer extends
AliasedTupleSubsetResultTransformer {
public static final AliasToEntityMapResultTransformer INSTANCE = new
AliasToEntityMapResultTransformer();
@@ -52,7 +51,7 @@
*/
public AliasToEntityMapResultTransformer() {
}
-
+
/**
* {@inheritDoc}
*/
@@ -66,7 +65,15 @@
}
return result;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
+ return false;
+ }
+
/**
* Serialization hook for ensuring singleton uniqueing.
*
Added:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasedTupleSubsetResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasedTupleSubsetResultTransformer.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/AliasedTupleSubsetResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,58 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.transform;
+
+/**
+ * An implementation of TupleSubsetResultTransformer that ignores a
+ * tuple element if its corresponding alias is null.
+ *
+ * @author Gail Badner
+ */
+public abstract class AliasedTupleSubsetResultTransformer
+ extends BasicTransformerAdapter
+ implements TupleSubsetResultTransformer {
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean[] includeInTransform(String[] aliases, int tupleLength) {
+ if ( aliases == null ) {
+ throw new IllegalArgumentException( "aliases cannot be null" );
+ }
+ if ( aliases.length != tupleLength ) {
+ throw new IllegalArgumentException(
+ "aliases and tupleLength must have the same length; " +
+ "aliases.length=" + aliases.length + "tupleLength=" +
tupleLength
+ );
+ }
+ boolean[] includeInTransform = new boolean[tupleLength];
+ for ( int i = 0 ; i < aliases.length ; i++ ) {
+ if ( aliases[ i ] != null ) {
+ includeInTransform[ i ] = true;
+ }
+ }
+ return includeInTransform;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/CacheableResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/CacheableResultTransformer.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/CacheableResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,347 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.transform;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.List;
+
+import org.hibernate.type.Type;
+import org.hibernate.util.ArrayHelper;
+
+/**
+ * A ResultTransformer that is used to transfor tuples to a value(s)
+ * that can be cached.
+ *
+ * @author Gail Badner
+ */
+public class CacheableResultTransformer implements ResultTransformer {
+
+ // would be nice to be able to have this class extend
+ // PassThroughResultTransformer, but the default constructor
+ // is private (as it should be for a singleton)
+ private final static PassThroughResultTransformer ACTUAL_TRANSFORMER =
+ PassThroughResultTransformer.INSTANCE;
+ private final int tupleLength;
+ private final int tupleSubsetLength;
+
+ // array with the i-th element indicating whether the i-th
+ // expression returned by a query is included in the tuple;
+ // IMPLLEMENTATION NOTE:
+ // "joined" and "fetched" associations may use the same SQL,
+ // but result in different tuple and cached values. This is
+ // because "fetched" associations are excluded from the tuple.
+ // includeInTuple provides a way to distinguish these 2 cases.
+ private final boolean[] includeInTuple;
+
+ // indexes for tuple that are included in the transformation;
+ // set to null if all elements in the tuple are included
+ private final int[] includeInTransformIndex;
+
+ /**
+ * Returns a CacheableResultTransformer that is used to transform
+ * tuples to a value(s) that can be cached.
+ *
+ * @param transformer - result transformer that will ultimately be
+ * be used (after caching results)
+ * @param aliases - the aliases that correspond to the tuple;
+ * if it is non-null, its length must equal the number
+ * of true elements in includeInTuple[]
+ * @param includeInTuple - array with the i-th element indicating
+ * whether the i-th expression returned by a query is
+ * included in the tuple; the number of true values equals
+ * the length of the tuple that will be transformed;
+ * must be non-null
+ * @return a CacheableResultTransformer that is used to transform
+ * tuples to a value(s) that can be cached.
+ */
+ public static CacheableResultTransformer create(ResultTransformer transformer,
+ String[] aliases,
+ boolean[] includeInTuple) {
+ return transformer instanceof TupleSubsetResultTransformer ?
+ create( ( TupleSubsetResultTransformer ) transformer, aliases, includeInTuple ) :
+ create( includeInTuple )
+ ;
+ }
+
+ /**
+ * Returns a CacheableResultTransformer that is used to transform
+ * tuples to a value(s) that can be cached.
+ *
+ * @param transformer - a tuple subset result transformer;
+ * must be non-null;
+ * @param aliases - the aliases that correspond to the tuple;
+ * if it is non-null, its length must equal the number
+ * of true elements in includeInTuple[]
+ * @param includeInTuple - array with the i-th element indicating
+ * whether the i-th expression returned by a query is
+ * included in the tuple; the number of true values equals
+ * the length of the tuple that will be transformed;
+ * must be non-null
+ * @return a CacheableResultTransformer that is used to transform
+ * tuples to a value(s) that can be cached.
+ */
+ private static CacheableResultTransformer create(TupleSubsetResultTransformer
transformer,
+ String[] aliases,
+ boolean[] includeInTuple) {
+ if ( transformer == null ) {
+ throw new IllegalArgumentException( "transformer cannot be null" );
+ }
+ int tupleLength = ArrayHelper.countTrue( includeInTuple );
+ if ( aliases != null && aliases.length != tupleLength ) {
+ throw new IllegalArgumentException(
+ "if aliases is not null, then the length of aliases[] must equal the number of
true elements in includeInTuple; " +
+ "aliases.length=" + aliases.length + "tupleLength=" +
tupleLength
+ );
+ }
+ return new CacheableResultTransformer(
+ includeInTuple,
+ transformer.includeInTransform( aliases, tupleLength )
+ );
+ }
+
+ /**
+ * Returns a CacheableResultTransformer that is used to transform
+ * tuples to a value(s) that can be cached.
+ *
+ * @param includeInTuple - array with the i-th element indicating
+ * whether the i-th expression returned by a query is
+ * included in the tuple; the number of true values equals
+ * the length of the tuple that will be transformed;
+ * must be non-null
+ * @return a CacheableResultTransformer that is used to transform
+ * tuples to a value(s) that can be cached.
+ */
+ private static CacheableResultTransformer create(boolean[] includeInTuple) {
+ return new CacheableResultTransformer( includeInTuple, null );
+ }
+
+ private CacheableResultTransformer(boolean[] includeInTuple, boolean[]
includeInTransform) {
+ if ( includeInTuple == null ) {
+ throw new IllegalArgumentException( "includeInTuple cannot be null" );
+ }
+ this.includeInTuple = includeInTuple;
+ tupleLength = ArrayHelper.countTrue( includeInTuple );
+ tupleSubsetLength = (
+ includeInTransform == null ?
+ tupleLength :
+ ArrayHelper.countTrue( includeInTransform )
+ );
+ if ( tupleSubsetLength == tupleLength ) {
+ includeInTransformIndex = null;
+ }
+ else {
+ includeInTransformIndex = new int[tupleSubsetLength];
+ for ( int i = 0, j = 0 ; i < includeInTransform.length ; i++ ) {
+ if ( includeInTransform[ i ] ) {
+ includeInTransformIndex[ j ] = i;
+ j++;
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object transformTuple(Object[] tuple, String aliases[]) {
+ if ( aliases != null && aliases.length != tupleLength ) {
+ throw new IllegalStateException(
+ "aliases expected length is " + tupleLength +
+ "; actual length is " + aliases.length );
+ }
+ // really more correct to pass index( aliases.getClass(), aliases )
+ // as the 2nd arg to the following statement;
+ // passing null instead because it ends up being ignored.
+ return ACTUAL_TRANSFORMER.transformTuple( index( tuple.getClass(), tuple ), null );
+ }
+
+ /**
+ * Re-transforms, if necessary, a List of values previously
+ * transformed by this (or an equivalent) CacheableResultTransformer.
+ * Each element of the list is re-transformed in place (i.e, List
+ * elements are replaced with re-transformed values) and the original
+ * List is returned.
+ * <p/>
+ * If re-transformation is unnecessary, the original List is returned
+ * unchanged.
+ *
+ * @param transformedResults - results that were previously transformed
+ * @param aliases - the aliases that correspond to the untransformed tuple;
+ * @param transformer - the transformer for the re-transformation
+ * @return transformedResults, with each element re-transformed (if nececessary)
+ */
+ public List retransformResults(List transformedResults,
+ String aliases[],
+ ResultTransformer transformer,
+ boolean[] includeInTuple) {
+ if ( transformer == null ) {
+ throw new IllegalArgumentException( "transformer cannot be null" );
+ }
+ if ( ! this.equals( create( transformer, aliases, includeInTuple ) ) ) {
+ throw new IllegalStateException(
+ "this CacheableResultTransformer is inconsistent with specified arguments;
cannot re-transform"
+ );
+ }
+ boolean requiresRetransform = true;
+ String[] aliasesToUse = aliases == null ? null : index( ( aliases.getClass() ), aliases
);
+ if ( transformer == ACTUAL_TRANSFORMER ) {
+ requiresRetransform = false;
+ }
+ else if ( transformer instanceof TupleSubsetResultTransformer ) {
+ requiresRetransform = ! ( ( TupleSubsetResultTransformer ) transformer
).isTransformedValueATupleElement(
+ aliasesToUse,
+ tupleLength
+ );
+ }
+ if ( requiresRetransform ) {
+ for ( int i = 0 ; i < transformedResults.size() ; i++ ) {
+ Object[] tuple = ACTUAL_TRANSFORMER.untransformToTuple(
+ transformedResults.get( i ),
+ tupleSubsetLength == 1
+ );
+ transformedResults.set( i, transformer.transformTuple( tuple, aliasesToUse ) );
+ }
+ }
+ return transformedResults;
+ }
+
+ /**
+ * Untransforms, if necessary, a List of values previously
+ * transformed by this (or an equivalent) CacheableResultTransformer.
+ * Each element of the list is untransformed in place (i.e, List
+ * elements are replaced with untransformed values) and the original
+ * List is returned.
+ * <p/>
+ * If not unnecessary, the original List is returned
+ * unchanged.
+ * <p/>
+ * NOTE: If transformed values are a subset of the original
+ * tuple, then, on return, elements corresponding to
+ * excluded tuple elements will be null.
+ * @param results - results that were previously transformed
+ * @return results, with each element untransformed (if nececessary)
+ */
+ public List untransformToTuples(List results) {
+ if ( includeInTransformIndex == null ) {
+ results = ACTUAL_TRANSFORMER.untransformToTuples(
+ results,
+ tupleSubsetLength == 1
+ );
+ }
+ else {
+ for ( int i = 0 ; i < results.size() ; i++ ) {
+ Object[] tuple = ACTUAL_TRANSFORMER.untransformToTuple(
+ results.get( i ),
+ tupleSubsetLength == 1
+ );
+ results.set( i, unindex( tuple.getClass(), tuple ) );
+ }
+
+ }
+ return results;
+ }
+
+ /**
+ * Returns the result types for the transformed value.
+ * @param tupleResultTypes
+ * @return
+ */
+ public Type[] getCachedResultTypes(Type[] tupleResultTypes) {
+ return tupleLength != tupleSubsetLength ?
+ index( tupleResultTypes.getClass(), tupleResultTypes ) :
+ tupleResultTypes
+ ;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List transformList(List list) {
+ return list;
+ }
+
+ private <T> T[] index(Class<? extends T[]> clazz, T[] objects) {
+ T[] objectsIndexed = objects;
+ if ( objects != null &&
+ includeInTransformIndex != null &&
+ objects.length != tupleSubsetLength ) {
+ objectsIndexed = clazz.cast( Array.newInstance( clazz.getComponentType(),
tupleSubsetLength ) );
+ for ( int i = 0 ; i < tupleSubsetLength; i++ ) {
+ objectsIndexed[ i ] = objects[ includeInTransformIndex[ i ] ];
+ }
+ }
+ return objectsIndexed;
+ }
+
+ private <T> T[] unindex(Class<? extends T[]> clazz, T[] objects) {
+ T[] objectsUnindexed = objects;
+ if ( objects != null &&
+ includeInTransformIndex != null &&
+ objects.length != tupleLength ) {
+ objectsUnindexed = clazz.cast( Array.newInstance( clazz.getComponentType(),
tupleLength ) );
+ for ( int i = 0 ; i < tupleSubsetLength; i++ ) {
+ objectsUnindexed[ includeInTransformIndex[ i ] ] = objects[ i ];
+ }
+ }
+ return objectsUnindexed;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ CacheableResultTransformer that = ( CacheableResultTransformer ) o;
+
+ if ( tupleLength != that.tupleLength ) {
+ return false;
+ }
+ if ( tupleSubsetLength != that.tupleSubsetLength ) {
+ return false;
+ }
+ if ( !Arrays.equals( includeInTuple, that.includeInTuple ) ) {
+ return false;
+ }
+ if ( !Arrays.equals( includeInTransformIndex, that.includeInTransformIndex ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = tupleLength;
+ result = 31 * result + tupleSubsetLength;
+ result = 31 * result + ( includeInTuple != null ? Arrays.hashCode( includeInTuple ) : 0
);
+ result = 31 * result + ( includeInTransformIndex != null ? Arrays.hashCode(
includeInTransformIndex ) : 0 );
+ return result;
+ }
+}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -24,7 +24,6 @@
*/
package org.hibernate.transform;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -42,7 +41,7 @@
*
* @author Steve Ebersole
*/
-public class DistinctResultTransformer extends BasicTransformerAdapter implements
Serializable {
+public class DistinctResultTransformer extends BasicTransformerAdapter {
public static final DistinctResultTransformer INSTANCE = new
DistinctResultTransformer();
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/DistinctRootEntityResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -37,7 +37,7 @@
* @author Gavin King
* @author Steve Ebersole
*/
-public class DistinctRootEntityResultTransformer implements ResultTransformer,
Serializable {
+public class DistinctRootEntityResultTransformer implements TupleSubsetResultTransformer
{
public static final DistinctRootEntityResultTransformer INSTANCE = new
DistinctRootEntityResultTransformer();
@@ -71,6 +71,20 @@
public List transformList(List list) {
return DistinctResultTransformer.INSTANCE.transformList( list );
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean[] includeInTransform(String[] aliases, int tupleLength) {
+ return RootEntityResultTransformer.INSTANCE.includeInTransform( aliases, tupleLength
);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength){
+ return RootEntityResultTransformer.INSTANCE.isTransformedValueATupleElement( null,
tupleLength );
+ }
/**
* Serialization hook for ensuring singleton uniqueing.
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/PassThroughResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -24,14 +24,15 @@
*/
package org.hibernate.transform;
-import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
/**
* ???
*
* @author max
*/
-public class PassThroughResultTransformer extends BasicTransformerAdapter implements
Serializable {
+public class PassThroughResultTransformer extends BasicTransformerAdapter implements
TupleSubsetResultTransformer {
public static final PassThroughResultTransformer INSTANCE = new
PassThroughResultTransformer();
@@ -46,6 +47,23 @@
public Object transformTuple(Object[] tuple, String[] aliases) {
return tuple.length==1 ? tuple[0] : tuple;
}
+
+ /* package-protected */
+ List untransformToTuples(List results, boolean isSingleResult) {
+ // untransform only if necessary; if transformed, do it in place;
+ if ( isSingleResult ) {
+ for ( int i = 0 ; i < results.size() ; i++ ) {
+ Object[] tuple = untransformToTuple( results.get( i ), isSingleResult);
+ results.set( i, tuple );
+ }
+ }
+ return results;
+ }
+
+ /* package-protected */
+ Object[] untransformToTuple(Object transformed, boolean isSingleResult ) {
+ return isSingleResult ? new Object[] { transformed } : ( Object[] ) transformed;
+ }
/**
* Serialization hook for ensuring singleton uniqueing.
@@ -56,14 +74,20 @@
return INSTANCE;
}
- public int hashCode() {
- // todo : we can remove this once the deprecated ctor can be made private...
- return PassThroughResultTransformer.class.getName().hashCode();
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
+ return tupleLength == 1;
}
- public boolean equals(Object other) {
- // todo : we can remove this once the deprecated ctor can be made private...
- return other != null && PassThroughResultTransformer.class.isInstance( other
);
+ /**
+ * {@inheritDoc}
+ */
+ public boolean[] includeInTransform(String[] aliases, int tupleLength) {
+ boolean[] includeInTransformedResult = new boolean[tupleLength];
+ Arrays.fill( includeInTransformedResult, true );
+ return includeInTransformedResult;
}
}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/RootEntityResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -24,8 +24,9 @@
*/
package org.hibernate.transform;
-import java.io.Serializable;
+import org.hibernate.util.ArrayHelper;
+
/**
* {@link ResultTransformer} implementation which limits the result tuple
* to only the "root entity".
@@ -36,7 +37,7 @@
* @author Gavin King
* @author Steve Ebersole
*/
-public final class RootEntityResultTransformer extends BasicTransformerAdapter implements
Serializable {
+public final class RootEntityResultTransformer extends BasicTransformerAdapter implements
TupleSubsetResultTransformer {
public static final RootEntityResultTransformer INSTANCE = new
RootEntityResultTransformer();
@@ -54,8 +55,29 @@
public Object transformTuple(Object[] tuple, String[] aliases) {
return tuple[ tuple.length-1 ];
}
-
+
/**
+ * {@inheritDoc}
+ */
+ public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean[] includeInTransform(String[] aliases, int tupleLength) {
+ boolean[] includeInTransform;
+ if( tupleLength==1 ){
+ includeInTransform = ArrayHelper.TRUE;
+ }
+ else {
+ includeInTransform = new boolean[tupleLength];
+ includeInTransform[tupleLength-1]=true;
+ }
+ return includeInTransform;
+ }
+ /**
* Serialization hook for ensuring singleton uniqueing.
*
* @return The singleton instance : {@link #INSTANCE}
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/ToListResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/ToListResultTransformer.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/ToListResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -24,7 +24,6 @@
*/
package org.hibernate.transform;
-import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
@@ -32,7 +31,7 @@
* Tranforms each result row from a tuple into a {@link List}, such that what
* you end up with is a {@link List} of {@link List Lists}.
*/
-public class ToListResultTransformer extends BasicTransformerAdapter implements
Serializable {
+public class ToListResultTransformer extends BasicTransformerAdapter {
public static final ToListResultTransformer INSTANCE = new ToListResultTransformer();
Added:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/TupleSubsetResultTransformer.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/TupleSubsetResultTransformer.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/transform/TupleSubsetResultTransformer.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,84 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.transform;
+
+/**
+ * A ResultTransformer that operates on "well-defined" and consistent
+ * subset of a tuple's elements.
+ *
+ * "Well-defined" means that:
+ * <ol>
+ * <li>
+ * the indexes of tuple elements accessed by a
+ * TupleSubsetResultTransformer depends only on the aliases
+ * and the number of elements in the tuple; i.e, it does
+ * not depend on the value of the tuple being transformed;
+ * </li>
+ * <li>
+ * any tuple elements included in the transformed value are
+ * unmodified by the transformation;
+ * </li>
+ * <li>
+ * transforming equivalent tuples with the same aliases multiple
+ * times results in transformed values that are equivalent;
+ * </li>
+ * <li>
+ * the result of transforming the tuple subset (only those
+ * elements accessed by the transformer) using only the
+ * corresponding aliases is equivalent to transforming the
+ * full tuple with the full array of aliases;
+ * </li>
+ * <li>
+ * the result of transforming a tuple with non-accessed tuple
+ * elements and corresponding aliases set to null
+ * is equivalent to transforming the full tuple with the
+ * full array of aliases;
+ * </li>
+ * </ol>
+ *
+ * @author Gail Badner
+ */
+public interface TupleSubsetResultTransformer extends ResultTransformer {
+ /**
+ * When a tuple is transformed, is the result a single element of the tuple?
+ *
+ * @param aliases - the aliases that correspond to the tuple
+ * @param tupleLength - the number of elements in the tuple
+ * @return true, if the transformed value is a single element of the tuple;
+ * false, otherwise.
+ */
+ boolean isTransformedValueATupleElement(String[] aliases, int tupleLength);
+
+ /**
+ * Returns an array with the i-th element indicating whether the i-th
+ * element of the tuple is included in the transformed value.
+ *
+ * @param aliases - the aliases that correspond to the tuple
+ * @param tupleLength - the number of elements in the tuple
+ * @return array with the i-th element indicating whether the i-th
+ * element of the tuple is included in the transformed value.
+ */
+ boolean[] includeInTransform(String[] aliases, int tupleLength);
+}
\ No newline at end of file
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/CompositeUserType.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/CompositeUserType.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/CompositeUserType.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -169,7 +169,7 @@
*
* @param value the object to be cached
* @param session
- * @return a cachable representation of the object
+ * @return a cacheable representation of the object
* @throws HibernateException
*/
public Serializable disassemble(Object value, SessionImplementor session) throws
HibernateException;
@@ -181,7 +181,7 @@
* @param cached the object to be cached
* @param session
* @param owner the owner of the cached object
- * @return a reconstructed object from the cachable representation
+ * @return a reconstructed object from the cacheable representation
* @throws HibernateException
*/
public Object assemble(Serializable cached, SessionImplementor session, Object owner)
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/EnhancedUserType.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/EnhancedUserType.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/EnhancedUserType.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -26,7 +26,7 @@
/**
* A custom type that may function as an identifier or
- * discriminator type, or may be marshalled to and from
+ * discriminator type, or may be marshaled to and from
* an XML document
*
* @author Gavin King
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/LoggableUserType.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/LoggableUserType.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/LoggableUserType.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -36,7 +36,7 @@
/**
* Generate a loggable string representation of the collection (value).
*
- * @param value The collection to be logged; guarenteed to be non-null and initialized.
+ * @param value The collection to be logged; guaranteed to be non-null and initialized.
* @param factory The factory.
* @return The loggable string representation.
*/
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserCollectionType.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserCollectionType.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserCollectionType.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -83,7 +83,7 @@
* but with the given anticipated size (i.e. accounting for initial size
* and perhaps load factor).
*
- * @param anticipatedSize The anticipated size of the instaniated collection
+ * @param anticipatedSize The anticipated size of the instantiated collection
* after we are done populating it. Note, may be negative to indicate that
* we not yet know anything about the anticipated size (i.e., when initializing
* from a result set row by row).
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserType.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserType.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/main/java/org/hibernate/usertype/UserType.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -146,7 +146,7 @@
* identifier values. (optional operation)
*
* @param value the object to be cached
- * @return a cachable representation of the object
+ * @return a cacheable representation of the object
* @throws HibernateException
*/
public Serializable disassemble(Object value) throws HibernateException;
@@ -157,7 +157,7 @@
*
* @param cached the object to be cached
* @param owner the owner of the cached object
- * @return a reconstructed object from the cachable representation
+ * @return a reconstructed object from the cacheable representation
* @throws HibernateException
*/
public Object assemble(Serializable cached, Object owner) throws HibernateException;
Modified:
core/branches/Branch_3_3_2_GA_CP/core/src/test/java/org/hibernate/cache/QueryKeyTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/core/src/test/java/org/hibernate/cache/QueryKeyTest.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/core/src/test/java/org/hibernate/cache/QueryKeyTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -20,21 +20,29 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
+ *
*/
package org.hibernate.cache;
+import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Map;
import junit.framework.TestCase;
import org.hibernate.EntityMode;
+import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
+import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
+import org.hibernate.transform.CacheableResultTransformer;
import org.hibernate.transform.DistinctResultTransformer;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import org.hibernate.transform.PassThroughResultTransformer;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.RootEntityResultTransformer;
+import org.hibernate.transform.ToListResultTransformer;
+import org.hibernate.transform.TupleSubsetResultTransformer;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.SerializationHelper;
@@ -46,19 +54,176 @@
public class QueryKeyTest extends TestCase {
private static final String QUERY_STRING = "the query string";
- public void testSerializedEquality() {
+ public static class AClass implements Serializable {
+ private String propAccessedByField;
+ private String propAccessedByMethod;
+ private int propValue;
+
+ public AClass() {
+ }
+
+ public AClass(String propAccessedByField) {
+ this.propAccessedByField = propAccessedByField;
+ }
+
+ public String getPropAccessedByMethod() {
+ return propAccessedByMethod;
+ }
+
+ public void setPropAccessedByMethod(String propAccessedByMethod) {
+ this.propAccessedByMethod = propAccessedByMethod;
+ }
+ }
+
+ public void testSerializedEqualityResultTransformer() throws Exception {
+ // settings are lazily initialized when calling transformTuple(),
+ // so they have not been initialized for the following test
+ // (it *should* be initialized before creating a QueryKey)
+ doResultTransformerTest( new AliasToBeanResultTransformer( AClass.class ), false );
+
+ // initialize settings for the next test
+ AliasToBeanResultTransformer transformer = new AliasToBeanResultTransformer(
AClass.class );
+ transformer.transformTuple(
+ new Object[] { "abc", "def" },
+ new String[] { "propAccessedByField", "propAccessedByMethod" }
+ );
+ doResultTransformerTest( transformer, false );
+
+ doResultTransformerTest( AliasToEntityMapResultTransformer.INSTANCE, true );
+ doResultTransformerTest( DistinctResultTransformer.INSTANCE, true );
+ doResultTransformerTest( DistinctRootEntityResultTransformer.INSTANCE, true );
+ doResultTransformerTest( PassThroughResultTransformer.INSTANCE, true );
+ doResultTransformerTest( RootEntityResultTransformer.INSTANCE, true );
+ doResultTransformerTest( ToListResultTransformer.INSTANCE, true );
+ }
+
+ // Reproduces HHH-5628; commented out because FailureExpected is not working here...
+ /*
+ public void testAliasToBeanConstructorFailureExpected() throws Exception {
+ // AliasToBeanConstructorResultTransformer is not Serializable because
+ // java.lang.reflect.Constructor is not Serializable;
+ doResultTransformerTest(
+ new AliasToBeanConstructorResultTransformer( AClass.class.getConstructor(
String.class ) ), false
+ );
+ }
+ */
+
+ private void doResultTransformerTest(ResultTransformer transformer, boolean isSingleton)
{
+ Map transformerMap = new HashMap();
+
+ transformerMap.put( transformer, "" );
+ assert transformerMap.size() == 1 : "really messed up";
+ Object old = transformerMap.put( transformer, "value" );
+ assert old != null && transformerMap.size() == 1 : "apparent QueryKey
equals/hashCode issue";
+
+ // finally, lets serialize it and see what happens
+ ResultTransformer transformer2 = ( ResultTransformer ) SerializationHelper.clone(
transformer );
+ old = transformerMap.put( transformer2, "new value" );
+ assert old != null && transformerMap.size() == 1 : "deserialization did
not set hashCode or equals properly";
+ if ( isSingleton ) {
+ assert transformer == transformer2: "deserialization issue for singleton
transformer";
+ }
+ else {
+ assert transformer != transformer2: "deserialization issue for non-singleton
transformer";
+ }
+ assert transformer.equals( transformer2 ): "deep copy issue";
+ }
+
+ public void testSerializedEquality() throws Exception {
doTest( buildBasicKey( null ) );
+
+ doTest( buildBasicKey( CacheableResultTransformer.create( null, null, new boolean[] {
true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( null, new String[] { null },
new boolean[] { true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( null, new String[] {
"a" }, new boolean[] { true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( null, null, new boolean[] {
false, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( null, new String[] {
"a" }, new boolean[] { true, false } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( null, new String[] {
"a", null }, new boolean[] { true, true } ) ) );
}
- public void testSerializedEqualityWithResultTransformer() {
- doTest( buildBasicKey( RootEntityResultTransformer.INSTANCE ) );
- doTest( buildBasicKey( DistinctRootEntityResultTransformer.INSTANCE ) );
- doTest( buildBasicKey( DistinctResultTransformer.INSTANCE ) );
- doTest( buildBasicKey( AliasToEntityMapResultTransformer.INSTANCE ) );
- doTest( buildBasicKey( PassThroughResultTransformer.INSTANCE ) );
+ public void testSerializedEqualityWithTupleSubsetResultTransfprmer() throws Exception {
+ doTestWithTupleSubsetResultTransformer(
+ new AliasToBeanResultTransformer( AClass.class ),
+ new String[] { "propAccessedByField", "propAccessedByMethod" }
+ );
+ doTestWithTupleSubsetResultTransformer( AliasToEntityMapResultTransformer.INSTANCE, new
String[] { "a", "b" } );
+ doTestWithTupleSubsetResultTransformer( DistinctRootEntityResultTransformer.INSTANCE,
new String[] { "a", "b" } );
+ doTestWithTupleSubsetResultTransformer( PassThroughResultTransformer.INSTANCE, new
String[] { "a", "b" } );
+ doTestWithTupleSubsetResultTransformer( RootEntityResultTransformer.INSTANCE, new
String[] { "a", "b" } );
+ // The following are not TupleSubsetResultTransformers:
+ // DistinctResultTransformer.INSTANCE
+ // ToListResultTransformer.INSTANCE
}
- private QueryKey buildBasicKey(ResultTransformer resultTransformer) {
+ public void doTestWithTupleSubsetResultTransformer(TupleSubsetResultTransformer
transformer,
+ String[] aliases) throws Exception {
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 0 ], aliases[ 1 ] },
+ new boolean[] { true, true } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 0 ], aliases[ 1 ] },
+ new boolean[] { true, true, false } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 1 ] },
+ new boolean[] { true } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { null, aliases[ 1 ] },
+ new boolean[] { true, true } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 0 ], null },
+ new boolean[] { true, true } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 0 ] },
+ new boolean[] { false, true } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 0 ] },
+ new boolean[] { true, false } )
+ ) );
+ doTest( buildBasicKey(
+ CacheableResultTransformer.create(
+ transformer,
+ new String[] { aliases[ 0 ] },
+ new boolean[] { false, true, false } )
+ ) );
+ if ( ! ( transformer instanceof AliasedTupleSubsetResultTransformer ) ) {
+ doTestWithTupleSubsetResultTransformerNullAliases( transformer );
+ }
+ }
+
+ public void
doTestWithTupleSubsetResultTransformerNullAliases(TupleSubsetResultTransformer
transformer) throws Exception {
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] { true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] { true, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] { true, true, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] { false, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] { true, false } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] { false, true, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] {true, false, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] {true, true, false } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] {false, false, true } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] {false, true, false } ) ) );
+ doTest( buildBasicKey( CacheableResultTransformer.create( transformer, null, new
boolean[] {false, false, true } ) ) );
+ }
+
+ private QueryKey buildBasicKey(CacheableResultTransformer resultTransformer) {
return new QueryKey(
QUERY_STRING,
ArrayHelper.EMPTY_TYPE_ARRAY, // positional param types
@@ -73,18 +238,34 @@
}
private void doTest(QueryKey key) {
- HashMap map = new HashMap();
+ Map keyMap = new HashMap();
+ Map transformerMap = new HashMap();
- map.put( key, "" );
- assert map.size() == 1 : "really messed up";
+ keyMap.put( key, "" );
+ assert keyMap.size() == 1 : "really messed up";
+ Object old = keyMap.put( key, "value" );
+ assert old != null && keyMap.size() == 1 : "apparent QueryKey
equals/hashCode issue";
- Object old = map.put( key, "value" );
- assert old != null && map.size() == 1 : "apparent QueryKey equals/hashCode
issue";
+ if ( key.getResultTransformer() != null ) {
+ transformerMap.put( key.getResultTransformer(), "" );
+ assert transformerMap.size() == 1 : "really messed up";
+ old = transformerMap.put( key.getResultTransformer(), "value" );
+ assert old != null && transformerMap.size() == 1 : "apparent QueryKey
equals/hashCode issue";
+ }
// finally, lets serialize it and see what happens
QueryKey key2 = ( QueryKey ) SerializationHelper.clone( key );
assert key != key2 : "deep copy issue";
- old = map.put( key2, "new value" );
- assert old != null && map.size() == 1 : "deserialization did not set
hashCode or equals properly";
+ old = keyMap.put( key2, "new value" );
+ assert old != null && keyMap.size() == 1 : "deserialization did not set
hashCode or equals properly";
+ if ( key.getResultTransformer() == null ) {
+ assert key2.getResultTransformer() == null;
+ }
+ else {
+ old = transformerMap.put( key2.getResultTransformer(), "new value" );
+ assert old != null && transformerMap.size() == 1 : "deserialization did
not set hashCode or equals properly";
+ assert key.getResultTransformer() != key2.getResultTransformer():
"deserialization issue for non-singleton transformer";
+ assert key.getResultTransformer().equals( key2.getResultTransformer() ): "deep
copy issue";
+ }
}
}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/AbstractQueryCacheResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/AbstractQueryCacheResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/AbstractQueryCacheResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,2561 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Criteria;
+import org.hibernate.FetchMode;
+import org.hibernate.Hibernate;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Property;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.transform.AliasToBeanConstructorResultTransformer;
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.transform.Transformers;
+import org.hibernate.type.Type;
+import org.hibernate.util.ReflectHelper;
+
+/**
+ * @author Gail Badner
+ */
+public abstract class AbstractQueryCacheResultTransformerTest extends FunctionalTestCase
{
+
+ private Student yogiExpected;
+ private Student shermanExpected;
+ private CourseMeeting courseMeetingExpected1;
+ private CourseMeeting courseMeetingExpected2;
+ private Course courseExpected;
+ private Enrolment yogiEnrolmentExpected;
+ private Enrolment shermanEnrolmentExpected;
+
+ public AbstractQueryCacheResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "querycache/Enrolment.hbm.xml" };
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( Environment.USE_QUERY_CACHE, "true" );
+ cfg.setProperty( Environment.CACHE_REGION_PREFIX, "foo" );
+ cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" );
+ cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
+ }
+
+ protected abstract class CriteriaExecutor extends QueryExecutor {
+ protected abstract Criteria getCriteria(Session s) throws Exception;
+ protected Object getResults(Session s, boolean isSingleResult) throws Exception {
+ Criteria criteria = getCriteria( s ).setCacheable( getQueryCacheMode() !=
CacheMode.IGNORE ).setCacheMode( getQueryCacheMode() );
+ return ( isSingleResult ? criteria.uniqueResult() : criteria.list() );
+ }
+ }
+
+ protected abstract class HqlExecutor extends QueryExecutor {
+ protected abstract Query getQuery(Session s);
+ protected Object getResults(Session s, boolean isSingleResult) {
+ Query query = getQuery( s ).setCacheable( getQueryCacheMode() != CacheMode.IGNORE
).setCacheMode( getQueryCacheMode() );
+ return ( isSingleResult ? query.uniqueResult() : query.list() );
+ }
+ }
+
+ protected abstract class QueryExecutor {
+ public Object execute(boolean isSingleResult) throws Exception{
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ Object result = null;
+ try {
+ result = getResults( s, isSingleResult );
+ t.commit();
+ }
+ catch ( Exception ex ) {
+ t.rollback();
+ throw ex;
+ }
+ finally {
+ s.close();
+ }
+ return result;
+ }
+ protected abstract Object getResults(Session s, boolean isSingleResult) throws
Exception;
+ }
+
+ protected interface ResultChecker {
+ void check(Object results);
+ }
+
+ protected abstract CacheMode getQueryCacheMode();
+
+ protected boolean areDynamicNonLazyAssociationsChecked() {
+ return true;
+ }
+
+ protected void createData() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+
+ courseExpected = new Course();
+ courseExpected.setCourseCode( "HIB" );
+ courseExpected.setDescription( "Hibernate Training" );
+ courseMeetingExpected1 = new CourseMeeting( courseExpected, "Monday", 1,
"1313 Mockingbird Lane" );
+ courseMeetingExpected2 = new CourseMeeting( courseExpected, "Tuesday", 2,
"1313 Mockingbird Lane" );
+ courseExpected.getCourseMeetings().add( courseMeetingExpected1 );
+ courseExpected.getCourseMeetings().add( courseMeetingExpected2 );
+ s.save( courseExpected );
+
+ yogiExpected = new Student();
+ yogiExpected.setName( "Yogi" );
+ yogiExpected.setStudentNumber( 111 );
+ yogiExpected.setPreferredCourse( courseExpected );
+ List yogiSecretCodes = new ArrayList();
+ yogiSecretCodes.add( Integer.valueOf( 0 ) );
+ yogiExpected.setSecretCodes( yogiSecretCodes );
+ s.save( yogiExpected );
+
+ Address address1 = new Address( yogiExpected, "home", "1 Main
Street", "Podunk", "WA", "98000", "USA" );
+ Address address2 = new Address( yogiExpected, "work", "2 Main
Street", "NotPodunk", "WA", "98001", "USA"
);
+ yogiExpected.getAddresses().put( address1.getAddressType(), address1 );
+ yogiExpected.getAddresses().put( address2.getAddressType(), address2 );
+ s.save( address1 );
+ s.save( address2 );
+
+ shermanExpected = new Student();
+ shermanExpected.setName( "Sherman" );
+ shermanExpected.setStudentNumber( 999 );
+ List shermanSecretCodes = new ArrayList();
+ shermanSecretCodes.add( Integer.valueOf( 1 ) );
+ shermanSecretCodes.add( Integer.valueOf( 2 ) );
+ shermanExpected.setSecretCodes( shermanSecretCodes );
+ s.save( shermanExpected );
+
+ shermanEnrolmentExpected = new Enrolment();
+ shermanEnrolmentExpected.setCourse( courseExpected );
+ shermanEnrolmentExpected.setCourseCode( courseExpected.getCourseCode() );
+ shermanEnrolmentExpected.setSemester( ( short ) 1 );
+ shermanEnrolmentExpected.setYear( ( short ) 1999 );
+ shermanEnrolmentExpected.setStudent( shermanExpected );
+ shermanEnrolmentExpected.setStudentNumber( shermanExpected.getStudentNumber() );
+ shermanExpected.getEnrolments().add( shermanEnrolmentExpected );
+ s.save( shermanEnrolmentExpected );
+
+ yogiEnrolmentExpected = new Enrolment();
+ yogiEnrolmentExpected.setCourse( courseExpected );
+ yogiEnrolmentExpected.setCourseCode( courseExpected.getCourseCode() );
+ yogiEnrolmentExpected.setSemester( ( short ) 3 );
+ yogiEnrolmentExpected.setYear( ( short ) 1998 );
+ yogiEnrolmentExpected.setStudent( yogiExpected );
+ yogiEnrolmentExpected.setStudentNumber( yogiExpected.getStudentNumber() );
+ yogiExpected.getEnrolments().add( yogiEnrolmentExpected );
+ s.save( yogiEnrolmentExpected );
+
+ t.commit();
+ s.close();
+ }
+
+ protected void deleteData() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+/*
+ List students = s.createQuery( "from Student" ).list();
+ for ( Iterator it = students.iterator(); it.hasNext(); ) {
+ s.delete( it.next() );
+ }
+ s.createQuery( "delete from Enrolment" ).executeUpdate();
+ s.createQuery( "delete from CourseMeeting" ).executeUpdate();
+ s.createQuery( "delete from Course" ).executeUpdate();
+*/
+ s.delete( yogiExpected );
+ s.delete( shermanExpected );
+ s.delete( yogiEnrolmentExpected );
+ s.delete( shermanEnrolmentExpected );
+ s.delete( courseMeetingExpected1 );
+ s.delete( courseMeetingExpected2 );
+ s.delete( courseExpected );
+ t.commit();
+ s.close();
+ }
+
+
+ public void testAliasToEntityMapNoProjectionList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.enrolments", "e", Criteria.LEFT_JOIN )
+ .createAlias( "e.course", "c", Criteria.LEFT_JOIN )
+ .setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.enrolments e left join
e.course c order by s.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ assertEquals( 3, yogiMap.size() );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( 3, shermanMap.size() );
+ assertEquals( yogiExpected, yogiMap.get( "s" ) );
+ assertEquals( yogiEnrolmentExpected, yogiMap.get( "e" ) );
+ assertEquals( courseExpected, yogiMap.get( "c" ) );
+ assertEquals( shermanExpected, shermanMap.get( "s" ) );
+ assertEquals( shermanEnrolmentExpected, shermanMap.get( "e" ) );
+ assertEquals( courseExpected, shermanMap.get( "c" ) );
+ assertSame( ( ( Map ) resultList.get( 0 ) ).get( "c" ), shermanMap.get(
"c" ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToEntityMapNoProjectionMultiAndNullList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "p", Criteria.LEFT_JOIN )
+ .createAlias( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.preferredCourse p left join
s.addresses a order by s.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 3, resultList.size() );
+ Map yogiMap1 = ( Map ) resultList.get( 0 );
+ assertEquals( 3, yogiMap1.size() );
+ Map yogiMap2 = ( Map ) resultList.get( 1 );
+ assertEquals( 3, yogiMap2.size() );
+ Map shermanMap = ( Map ) resultList.get( 2 );
+ assertEquals( 3, shermanMap.size() );
+ assertEquals( yogiExpected, yogiMap1.get( "s" ) );
+ assertEquals( courseExpected, yogiMap1.get( "p" ) );
+ Address yogiAddress1 = ( Address ) yogiMap1.get( "a" );
+ assertEquals( yogiExpected.getAddresses().get( yogiAddress1.getAddressType() ),
+ yogiMap1.get( "a" ));
+ assertEquals( yogiExpected, yogiMap2.get( "s" ) );
+ assertEquals( courseExpected, yogiMap2.get( "p" ) );
+ Address yogiAddress2 = ( Address ) yogiMap2.get( "a" );
+ assertEquals( yogiExpected.getAddresses().get( yogiAddress2.getAddressType() ),
+ yogiMap2.get( "a" ));
+ assertSame( yogiMap1.get( "s" ), yogiMap2.get( "s" ) );
+ assertSame( yogiMap1.get( "p" ), yogiMap2.get( "p" ) );
+ assertFalse( yogiAddress1.getAddressType().equals( yogiAddress2.getAddressType() )
);
+ assertEquals( shermanExpected, shermanMap.get( "s" ) );
+ assertEquals( shermanExpected.getPreferredCourse(), shermanMap.get( "p" )
);
+ assertNull( shermanMap.get( "a") );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToEntityMapNoProjectionNullAndNonNullAliasList() throws Exception
{
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP )
+ .createCriteria( "s.preferredCourse", Criteria.INNER_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.addresses a left join
s.preferredCourse order by s.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap1 = ( Map ) resultList.get( 0 );
+ assertEquals( 2, yogiMap1.size() );
+ Map yogiMap2 = ( Map ) resultList.get( 1 );
+ assertEquals( 2, yogiMap2.size() );
+ assertEquals( yogiExpected, yogiMap1.get( "s" ) );
+ Address yogiAddress1 = ( Address ) yogiMap1.get( "a" );
+ assertEquals( yogiExpected.getAddresses().get( yogiAddress1.getAddressType() ),
+ yogiMap1.get( "a" ));
+ assertEquals( yogiExpected, yogiMap2.get( "s" ) );
+ Address yogiAddress2 = ( Address ) yogiMap2.get( "a" );
+ assertEquals( yogiExpected.getAddresses().get( yogiAddress2.getAddressType() ),
+ yogiMap2.get( "a" ));
+ assertSame( yogiMap1.get( "s" ), yogiMap2.get( "s" ) );
+ assertFalse( yogiAddress1.getAddressType().equals( yogiAddress2.getAddressType() )
);
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testEntityWithNonLazyOneToManyUnique() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Course.class );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Course" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Course );
+ assertEquals( courseExpected, results );
+ assertTrue( Hibernate.isInitialized( ( ( Course ) courseExpected
).getCourseMeetings() ) );
+ assertEquals( courseExpected.getCourseMeetings(), ( ( Course ) courseExpected
).getCourseMeetings() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testEntityWithNonLazyManyToOneList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( CourseMeeting.class )
+ .addOrder( Order.asc( "id.day") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ protected Query getQuery(Session s) {
+ return s.createQuery( "from CourseMeeting order by id.day" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( courseMeetingExpected1, resultList.get( 0 ) );
+ assertEquals( courseMeetingExpected2, resultList.get( 1 ) );
+ assertTrue( Hibernate.isInitialized( ( ( CourseMeeting ) resultList.get( 0 )
).getCourse() ) );
+ assertTrue( Hibernate.isInitialized( ( ( CourseMeeting ) resultList.get( 1 )
).getCourse() ) );
+ assertEquals( courseExpected, ( ( CourseMeeting ) resultList.get( 0 ) ).getCourse()
);
+ assertEquals( courseExpected, ( ( CourseMeeting ) resultList.get( 1 ) ).getCourse()
);
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testEntityWithLazyAssnUnique() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .add( Restrictions.eq( "studentNumber",
shermanExpected.getStudentNumber() ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s where s.studentNumber =
:studentNumber" )
+ .setParameter( "studentNumber", shermanExpected.getStudentNumber() );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Student );
+ assertEquals( shermanExpected, results );
+ assertNotNull( ( ( Student ) results ).getEnrolments() );
+ assertFalse( Hibernate.isInitialized( ( ( Student ) results ).getEnrolments() ) );
+ assertNull( ( ( Student ) results ).getPreferredCourse() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ // should use RootEntityTransformer by default
+ public void testEntityWithLazyAssnList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class )
+ .addOrder( Order.asc( "studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student order by studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getEnrolments() );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getPreferredCourse() );
+ assertNotNull( ( ( Student ) resultList.get( 1 ) ).getEnrolments() );
+ assertNull( ( ( Student ) resultList.get( 1 ) ).getPreferredCourse() );
+ assertFalse( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getEnrolments() ) );
+ assertFalse( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getPreferredCourse() ) );
+ assertFalse( Hibernate.isInitialized( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ assertNull( ( ( Student ) resultList.get( 1 ) ).getPreferredCourse() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testEntityWithUnaliasedJoinFetchedLazyOneToManySingleElementList() throws
Exception {
+ // unaliased
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .setFetchMode( "enrolments", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutorUnaliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.enrolments order by
s.studentNumber" );
+ }
+ };
+
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getEnrolments() );
+ assertNotNull( ( ( Student ) resultList.get( 1 ) ).getEnrolments() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) resultList.get( 0 )
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( Student ) resultList.get( 1 )
).getEnrolments() );
+ }
+ }
+ };
+
+ runTest( hqlExecutorUnaliased, criteriaExecutorUnaliased, checker, false);
+ }
+
+ public void testJoinWithFetchJoinListCriteria() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "pc", Criteria.LEFT_JOIN )
+ .setFetchMode( "enrolments", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ // The following fails for criteria due to HHH-3524
+ //assertEquals( yogiExpected.getPreferredCourse(), ( ( Student ) resultList.get( 0 )
).getPreferredCourse() );
+ assertEquals( yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Student ) resultList.get( 0 ) ).getPreferredCourse().getCourseCode() );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertNull( ( ( Student ) resultList.get( 1 ) ).getPreferredCourse() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) resultList.get( 0 )
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( null, criteriaExecutor, checker, false );
+ }
+
+ public void testJoinWithFetchJoinListHql() throws Exception {
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.enrolments left join
s.preferredCourse order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects[ 0 ] );
+ assertEquals( yogiExpected.getPreferredCourse(), yogiObjects[ 1 ] );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanObjects[ 0 ] );
+ assertNull( shermanObjects[ 1 ] );
+ assertNull( ( ( Student ) shermanObjects[ 0 ] ).getPreferredCourse() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanObjects[ 0 ]
).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlExecutor, null, checker, false );
+ }
+
+ public void testJoinWithFetchJoinWithOwnerAndPropProjectedList() throws Exception {
+ HqlExecutor hqlSelectNewMapExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select s, s.name from Student s left join fetch
s.enrolments left join s.preferredCourse order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects[ 0 ] );
+ assertEquals( yogiExpected.getName(), yogiObjects[ 1 ] );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanObjects[ 0 ] );
+ assertEquals( shermanExpected.getName(), shermanObjects[ 1 ] );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanObjects[ 0 ]
).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlSelectNewMapExecutor, null, checker, false );
+ }
+
+ public void testJoinWithFetchJoinWithPropAndOwnerProjectedList() throws Exception {
+ HqlExecutor hqlSelectNewMapExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select s.name, s from Student s left join fetch
s.enrolments left join s.preferredCourse order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected.getName(), yogiObjects[ 0 ] );
+ assertEquals( yogiExpected, yogiObjects[ 1 ] );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected.getName(), shermanObjects[ 0 ] );
+ assertEquals( shermanExpected, shermanObjects[ 1 ] );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 1 ]
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiObjects[ 1 ]
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanObjects[ 1 ]
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanObjects[ 1 ]
).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlSelectNewMapExecutor, null, checker, false );
+ }
+
+ public void testJoinWithFetchJoinWithOwnerAndAliasedJoinedProjectedListHql() throws
Exception {
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select s, pc from Student s left join fetch s.enrolments
left join s.preferredCourse pc order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects[ 0 ] );
+ assertEquals(
+ yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Course ) yogiObjects[ 1 ] ).getCourseCode()
+ );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanObjects[ 0 ] );
+ assertNull( shermanObjects[ 1 ] );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertEquals( yogiExpected.getPreferredCourse(), yogiObjects[ 1 ] );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanObjects[ 0 ]
).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlExecutor, null, checker, false );
+ }
+
+ public void testJoinWithFetchJoinWithAliasedJoinedAndOwnerProjectedListHql() throws
Exception {
+ HqlExecutor hqlSelectNewMapExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select pc, s from Student s left join fetch s.enrolments
left join s.preferredCourse pc order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects[ 1 ] );
+ assertEquals(
+ yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Course ) yogiObjects[ 0 ] ).getCourseCode()
+ );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanObjects[ 1 ] );
+ assertNull( shermanObjects[ 0 ] );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertEquals( yogiExpected.getPreferredCourse(), yogiObjects[ 0 ] );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 1 ]
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiObjects[ 1 ]
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanObjects[ 1 ]
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanObjects[ 1 ]
).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlSelectNewMapExecutor, null, checker, false );
+ }
+
+ public void testEntityWithAliasedJoinFetchedLazyOneToManySingleElementListHql() throws
Exception {
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.enrolments e order by
s.studentNumber" );
+ }
+ };
+
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals(
+ yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Student ) resultList.get( 0 ) ).getPreferredCourse().getCourseCode()
+ );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertNull( ( ( Student ) resultList.get( 1 ) ).getPreferredCourse() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) resultList.get( 0 )
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ }
+ }
+ };
+
+ runTest( hqlExecutor, null, checker, false);
+ }
+
+ public void testEntityWithSelectFetchedLazyOneToManySingleElementListCriteria() throws
Exception {
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .setFetchMode( "enrolments", FetchMode.SELECT )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getEnrolments() );
+ assertFalse( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getEnrolments() ) );
+ assertNotNull( ( ( Student ) resultList.get( 1 ) ).getEnrolments() );
+ assertFalse( Hibernate.isInitialized( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ }
+ };
+
+ runTest( null, criteriaExecutorUnaliased, checker, false);
+ }
+
+ public void testEntityWithJoinFetchedLazyOneToManyMultiAndNullElementList() throws
Exception {
+ //unaliased
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .setFetchMode( "addresses", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutorUnaliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.addresses order by
s.studentNumber" );
+ }
+ };
+
+ //aliased
+ CriteriaExecutor criteriaExecutorAliased1 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .setFetchMode( "addresses", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased2 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .setFetchMode( "a", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased3 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .setFetchMode( "addresses", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased4 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .setFetchMode( "a", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutorAliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.addresses a order by
s.studentNumber" );
+ }
+ };
+
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 3, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertSame( resultList.get( 0 ), resultList.get( 1 ) );
+ assertEquals( shermanExpected, resultList.get( 2 ) );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getAddresses() );
+ assertNotNull( ( ( Student ) resultList.get( 1 ) ).getAddresses() );
+ assertNotNull( ( ( Student ) resultList.get( 2 ) ).getAddresses() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getAddresses() ) );
+ assertEquals( yogiExpected.getAddresses(), ( ( Student ) resultList.get( 0 )
).getAddresses() );
+ assertTrue( ( ( Student ) resultList.get( 2 ) ).getAddresses().isEmpty() );
+ }
+ }
+ };
+ runTest( hqlExecutorUnaliased, criteriaExecutorUnaliased, checker, false );
+ runTest( hqlExecutorAliased, criteriaExecutorAliased1, checker, false );
+ runTest( null, criteriaExecutorAliased2, checker, false );
+ runTest( null, criteriaExecutorAliased3, checker, false );
+ runTest( null, criteriaExecutorAliased4, checker, false );
+ }
+
+ public void testEntityWithJoinFetchedLazyManyToOneList() throws Exception {
+ // unaliased
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .setFetchMode( "preferredCourse", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutorUnaliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.preferredCourse order by
s.studentNumber" );
+ }
+ };
+
+ // aliased
+ CriteriaExecutor criteriaExecutorAliased1 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "pCourse",
Criteria.LEFT_JOIN )
+ .setFetchMode( "preferredCourse", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased2 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "pCourse",
Criteria.LEFT_JOIN )
+ .setFetchMode( "pCourse", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased3 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.preferredCourse", "pCourse",
Criteria.LEFT_JOIN )
+ .setFetchMode( "preferredCourse", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased4 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.preferredCourse", "pCourse",
Criteria.LEFT_JOIN )
+ .setFetchMode( "pCourse", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutorAliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join fetch s.preferredCourse pCourse
order by s.studentNumber" );
+ }
+ };
+
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertEquals( yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Student ) resultList.get( 0 ) ).getPreferredCourse().getCourseCode() );
+ assertNull( ( ( Student ) resultList.get( 1 ) ).getPreferredCourse() );
+ }
+ };
+ runTest( hqlExecutorUnaliased, criteriaExecutorUnaliased, checker, false );
+ runTest( hqlExecutorAliased, criteriaExecutorAliased1, checker, false );
+ runTest( null, criteriaExecutorAliased2, checker, false );
+ runTest( null, criteriaExecutorAliased3, checker, false );
+ runTest( null, criteriaExecutorAliased4, checker, false );
+ }
+
+ public void testEntityWithJoinFetchedLazyManyToOneUsingProjectionList() throws Exception
{
+ // unaliased
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Enrolment.class, "e" )
+ .createAlias( "e.student", "s", Criteria.LEFT_JOIN )
+ .setFetchMode( "student", FetchMode.JOIN )
+ .setFetchMode( "student.preferredCourse", FetchMode.JOIN )
+ .setProjection(
+ Projections.projectionList()
+ .add( Projections.property( "s.name" ) )
+ .add( Projections.property( "e.student" ) )
+ )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select s.name, s from Enrolment e left join e.student s
left join fetch s.preferredCourse order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( yogiExpected.getName(), yogiObjects[ 0 ] );
+ assertEquals( shermanExpected.getName(), shermanObjects[ 0 ] );
+ // The following fails for criteria due to HHH-1425
+ // assertEquals( yogiExpected, yogiObjects[ 1 ] );
+ // assertEquals( shermanExpected, shermanObjects[ 1 ] );
+ assertEquals( yogiExpected.getStudentNumber(), ( ( Student ) yogiObjects[ 1 ]
).getStudentNumber() );
+ assertEquals( shermanExpected.getStudentNumber(), ( ( Student ) shermanObjects[ 1 ]
).getStudentNumber() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ // The following fails for criteria due to HHH-1425
+ //assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 1 ]
).getPreferredCourse() ) );
+ //assertEquals( yogiExpected.getPreferredCourse(), ( ( Student ) yogiObjects[ 1 ]
).getPreferredCourse() );
+ //assertTrue( Hibernate.isInitialized( ( ( Student ) shermanObjects[ 1 ]
).getPreferredCourse() ) );
+ //assertEquals( shermanExpected.getPreferredCourse(), ( ( Student ) shermanObjects[
1 ] ).getPreferredCourse() );
+ }
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testEntityWithJoinedLazyOneToManySingleElementListCriteria() throws
Exception {
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.enrolments", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased1 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.enrolments", "e", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased2 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.enrolments", "e", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getEnrolments() );
+ assertNotNull( ( ( Student ) resultList.get( 1 ) ).getEnrolments() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) resultList.get( 0 )
).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 1 )
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( Student ) resultList.get( 1 )
).getEnrolments() );
+ }
+ }
+ };
+ runTest( null, criteriaExecutorUnaliased, checker, false );
+ runTest( null, criteriaExecutorAliased1, checker, false );
+ runTest( null, criteriaExecutorAliased2, checker, false );
+ }
+
+ public void testEntityWithJoinedLazyOneToManyMultiAndNullListCriteria() throws Exception
{
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.addresses", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased1 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased2 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.addresses", "a", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 3, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertSame( resultList.get( 0 ), resultList.get( 1 ) );
+ assertEquals( shermanExpected, resultList.get( 2 ) );
+ assertNotNull( ( ( Student ) resultList.get( 0 ) ).getAddresses() );
+ assertNotNull( ( ( Student ) resultList.get( 2 ) ).getAddresses() );
+ assertNotNull( ( ( Student ) resultList.get( 1 ) ).getAddresses() );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) resultList.get( 0 )
).getAddresses() ) );
+ assertEquals( yogiExpected.getAddresses(), ( ( Student ) resultList.get( 0 )
).getAddresses() );
+ assertTrue( ( ( Student ) resultList.get( 2 ) ).getAddresses().isEmpty() );
+ }
+ }
+ };
+ runTest( null, criteriaExecutorUnaliased, checker, false );
+ runTest( null, criteriaExecutorAliased1, checker, false );
+ runTest( null, criteriaExecutorAliased2, checker, false );
+ }
+
+ public void testEntityWithJoinedLazyManyToOneListCriteria() throws Exception {
+ CriteriaExecutor criteriaExecutorUnaliased = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.preferredCourse", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased1 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.preferredCourse", "p", Criteria.LEFT_JOIN
)
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ CriteriaExecutor criteriaExecutorAliased2 = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "p", Criteria.LEFT_JOIN )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiExpected, resultList.get( 0 ) );
+ assertEquals( shermanExpected, resultList.get( 1 ) );
+ assertEquals( yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Student ) resultList.get( 0 ) ).getPreferredCourse().getCourseCode() );
+ assertNull( ( ( Student ) resultList.get( 1 ) ).getPreferredCourse() );
+ }
+ };
+ runTest( null, criteriaExecutorUnaliased, checker, false );
+ runTest( null, criteriaExecutorAliased1, checker, false );
+ runTest( null, criteriaExecutorAliased2, checker, false );
+ }
+
+ public void testEntityWithJoinedLazyOneToManySingleElementListHql() throws Exception {
+ HqlExecutor hqlExecutorUnaliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.enrolments order by
s.studentNumber" );
+ }
+ };
+ HqlExecutor hqlExecutorAliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.enrolments e order by
s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertTrue( resultList.get( 0 ) instanceof Object[] );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects[ 0 ] );
+ assertEquals( yogiEnrolmentExpected, yogiObjects[ 1 ] );
+ assertTrue( resultList.get( 0 ) instanceof Object[] );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanObjects[ 0 ] );
+ assertEquals( shermanEnrolmentExpected, shermanObjects[ 1 ] );
+ }
+ };
+ runTest( hqlExecutorUnaliased, null, checker, false );
+ runTest( hqlExecutorAliased, null, checker, false );
+ }
+
+ public void testEntityWithJoinedLazyOneToManyMultiAndNullListHql() throws Exception {
+ HqlExecutor hqlExecutorUnaliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.addresses order by
s.studentNumber" );
+ }
+ };
+ HqlExecutor hqlExecutorAliased = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "from Student s left join s.addresses a order by
s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 3, resultList.size() );
+ assertTrue( resultList.get( 0 ) instanceof Object[] );
+ Object[] yogiObjects1 = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects1[ 0 ] );
+ Address address1 = ( Address ) yogiObjects1[ 1 ];
+ assertEquals( yogiExpected.getAddresses().get( address1.getAddressType() ), address1
);
+ Object[] yogiObjects2 = ( Object[] ) resultList.get( 1 );
+ assertSame( yogiObjects1[ 0 ], yogiObjects2[ 0 ] );
+ Address address2 = ( Address ) yogiObjects2[ 1 ];
+ assertEquals( yogiExpected.getAddresses().get( address2.getAddressType() ), address2
);
+ assertFalse( address1.getAddressType().equals( address2.getAddressType() ) );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 2 );
+ assertEquals( shermanExpected, shermanObjects[ 0 ] );
+ assertNull( shermanObjects[ 1 ] );
+ }
+ };
+ runTest( hqlExecutorUnaliased, null, checker, false );
+ runTest( hqlExecutorAliased, null, checker, false );
+ }
+
+ public void testEntityWithJoinedLazyManyToOneListHql() throws Exception {
+ HqlExecutor hqlExecutorUnaliased = new HqlExecutor() {
+ protected Query getQuery(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createQuery( "from Student s left join s.preferredCourse order by
s.studentNumber" );
+ }
+ };
+ HqlExecutor hqlExecutorAliased = new HqlExecutor() {
+ protected Query getQuery(Session s) {
+ // should use RootEntityTransformer by default
+ return s.createQuery( "from Student s left join s.preferredCourse p order by
s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiObjects[ 0 ] );
+ assertEquals( yogiExpected.getPreferredCourse(), yogiObjects[ 1 ] );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanObjects[ 0 ] );
+ assertNull( shermanObjects[ 1 ] );
+ }
+ };
+ runTest( hqlExecutorUnaliased, null, checker, false );
+ runTest( hqlExecutorAliased, null, checker, false );
+ }
+
+ public void testAliasToEntityMapOneProjectionList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection( Projections.property( "e.student" ).as(
"student" ) )
+ .addOrder( Order.asc( "e.studentNumber") )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student as student from Enrolment e order by
e.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( 1, yogiMap.size() );
+ assertEquals( 1, shermanMap.size() );
+ // TODO: following are initialized for hql and uninitialied for criteria; why?
+ // assertFalse( Hibernate.isInitialized( yogiMap.get( "student" ) ) );
+ // assertFalse( Hibernate.isInitialized( shermanMap.get( "student" ) ) );
+ assertTrue( yogiMap.get( "student" ) instanceof Student );
+ assertTrue( shermanMap.get( "student" ) instanceof Student );
+ assertEquals( yogiExpected.getStudentNumber(), ( ( Student ) yogiMap.get(
"student" ) ).getStudentNumber() );
+ assertEquals( shermanExpected.getStudentNumber(), ( ( Student ) shermanMap.get(
"student" ) ).getStudentNumber() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false);
+ }
+
+ public void testAliasToEntityMapMultiProjectionList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "e.student" ), "student" )
+ .add( Property.forName( "e.semester" ), "semester" )
+ .add( Property.forName( "e.year" ), "year" )
+ .add( Property.forName( "e.course" ), "course" )
+ )
+ .addOrder( Order.asc( "studentNumber") )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student as student, e.semester as semester,
e.year as year, e.course as course from Enrolment e order by e.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( 4, yogiMap.size() );
+ assertEquals( 4, shermanMap.size() );
+ assertTrue( yogiMap.get( "student" ) instanceof Student );
+ assertTrue( shermanMap.get( "student" ) instanceof Student );
+ // TODO: following are initialized for hql and uninitialied for criteria; why?
+ // assertFalse( Hibernate.isInitialized( yogiMap.get( "student" ) ) );
+ // assertFalse( Hibernate.isInitialized( shermanMap.get( "student" ) ) );
+ assertEquals( yogiExpected.getStudentNumber(), ( ( Student ) yogiMap.get(
"student" ) ).getStudentNumber() );
+ assertEquals( shermanExpected.getStudentNumber(), ( ( Student ) shermanMap.get(
"student" ) ).getStudentNumber() );
+ assertEquals( yogiEnrolmentExpected.getSemester(), yogiMap.get( "semester"
) );
+ assertEquals( yogiEnrolmentExpected.getYear(), yogiMap.get( "year" ) );
+ assertEquals( courseExpected, yogiMap.get( "course" ) );
+ assertEquals( shermanEnrolmentExpected.getSemester(), shermanMap.get(
"semester" ) );
+ assertEquals( shermanEnrolmentExpected.getYear(), shermanMap.get( "year" )
);
+ assertEquals( courseExpected, shermanMap.get( "course" ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToEntityMapMultiProjectionWithNullAliasList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "e.student" ), "student" )
+ .add( Property.forName( "e.semester" ) )
+ .add( Property.forName( "e.year" ) )
+ .add( Property.forName( "e.course" ), "course" )
+ )
+ .addOrder( Order.asc( "e.studentNumber") )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student as student, e.semester, e.year, e.course
as course from Enrolment e order by e.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ // TODO: following are initialized for hql and uninitialied for criteria; why?
+ // assertFalse( Hibernate.isInitialized( yogiMap.get( "student" ) ) );
+ // assertFalse( Hibernate.isInitialized( shermanMap.get( "student" ) ) );
+ assertTrue( yogiMap.get( "student" ) instanceof Student );
+ assertEquals( yogiExpected.getStudentNumber(), ( ( Student ) yogiMap.get(
"student" ) ).getStudentNumber() );
+ assertEquals( shermanExpected.getStudentNumber(), ( ( Student ) shermanMap.get(
"student" ) ).getStudentNumber() );
+ assertNull( yogiMap.get( "semester" ) );
+ assertNull( yogiMap.get( "year" ) );
+ assertEquals( courseExpected, yogiMap.get( "course" ) );
+ assertNull( shermanMap.get( "semester" ) );
+ assertNull( shermanMap.get( "year" ) );
+ assertEquals( courseExpected, shermanMap.get( "course" ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToEntityMapMultiAggregatedPropProjectionSingleResult() throws
Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class )
+ .setProjection(
+ Projections.projectionList()
+ .add( Projections.min( "studentNumber" ).as(
"minStudentNumber" ) )
+ .add( Projections.max( "studentNumber" ).as(
"maxStudentNumber" ) )
+ )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery(
+ "select min( e.studentNumber ) as minStudentNumber, max( e.studentNumber ) as
maxStudentNumber from Enrolment e" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Map );
+ Map resultMap = ( Map ) results;
+ assertEquals( 2, resultMap.size() );
+ assertEquals( yogiExpected.getStudentNumber(), resultMap.get(
"minStudentNumber" ) );
+ assertEquals( shermanExpected.getStudentNumber(), resultMap.get(
"maxStudentNumber" ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testOneNonEntityProjectionUnique() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection( Projections.property( "e.semester" ) )
+ .add( Restrictions.eq( "e.studentNumber",
shermanEnrolmentExpected.getStudentNumber() ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.semester from Enrolment e where e.studentNumber
= :studentNumber" )
+ .setParameter( "studentNumber",
shermanEnrolmentExpected.getStudentNumber() );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Short );
+ assertEquals( Short.valueOf( shermanEnrolmentExpected.getSemester() ), results );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testOneNonEntityProjectionList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection( Projections.property( "e.semester" ) )
+ .addOrder( Order.asc( "e.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.semester from Enrolment e order by
e.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ assertEquals( yogiEnrolmentExpected.getSemester(), resultList.get( 0 ) );
+ assertEquals( shermanEnrolmentExpected.getSemester(), resultList.get( 1 ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testListElementsProjectionList() throws Exception {
+ /*
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Student.class, "s" )
+ .createCriteria( "s.secretCodes" )
+ .setProjection( Projections.property( "s.secretCodes" ) )
+ .addOrder( Order.asc( "s.studentNumber") );
+ }
+ };
+ */
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select elements(s.secretCodes) from Student s" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 3, resultList.size() );
+ assertTrue( resultList.contains( yogiExpected.getSecretCodes().get( 0 ) ) );
+ assertTrue( resultList.contains( shermanExpected.getSecretCodes().get( 0 ) ) );
+ assertTrue( resultList.contains( shermanExpected.getSecretCodes().get( 1 ) ) );
+ }
+ };
+ runTest( hqlExecutor, null, checker, false );
+ }
+
+ public void testOneEntityProjectionUnique() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Enrolment.class )
+ .setProjection( Projections.property( "student" ) )
+ .add( Restrictions.eq( "studentNumber", Long.valueOf(
yogiExpected.getStudentNumber() ) ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student from Enrolment e where e.studentNumber =
:studentNumber" )
+ .setParameter( "studentNumber", Long.valueOf(
yogiExpected.getStudentNumber() ) );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Student );
+ Student student = ( Student ) results;
+ // TODO: following is initialized for hql and uninitialied for criteria; why?
+ //assertFalse( Hibernate.isInitialized( student ) );
+ assertEquals( yogiExpected.getStudentNumber(), student.getStudentNumber() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testOneEntityProjectionList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ // should use PassThroughTransformer by default
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection( Projections.property( "e.student" ) )
+ .addOrder( Order.asc( "e.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student from Enrolment e order by
e.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ // TODO: following is initialized for hql and uninitialied for criteria; why?
+ //assertFalse( Hibernate.isInitialized( resultList.get( 0 ) ) );
+ //assertFalse( Hibernate.isInitialized( resultList.get( 1 ) ) );
+ assertEquals( yogiExpected.getStudentNumber(), ( ( Student ) resultList.get( 0 )
).getStudentNumber() );
+ assertEquals( shermanExpected.getStudentNumber(), ( ( Student ) resultList.get( 1 )
).getStudentNumber() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiEntityProjectionUnique() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Enrolment.class )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "student" ) )
+ .add( Property.forName( "semester" ) )
+ .add( Property.forName( "year" ) )
+ .add( Property.forName( "course" ) )
+ )
+ .add( Restrictions.eq( "studentNumber", Long.valueOf(
shermanEnrolmentExpected.getStudentNumber() ) ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery(
+ "select e.student, e.semester, e.year, e.course from Enrolment e where
e.studentNumber = :studentNumber" )
+ .setParameter( "studentNumber",
shermanEnrolmentExpected.getStudentNumber() );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Object[] );
+ Object shermanObjects[] = ( Object [] ) results;
+ assertEquals( 4, shermanObjects.length );
+ assertNotNull( shermanObjects[ 0 ] );
+ assertTrue( shermanObjects[ 0 ] instanceof Student );
+ // TODO: following is initialized for hql and uninitialied for criteria; why?
+ //assertFalse( Hibernate.isInitialized( shermanObjects[ 0 ] ) );
+ assertEquals( shermanEnrolmentExpected.getSemester(), ( (Short) shermanObjects[ 1 ]
).shortValue() );
+ assertEquals( shermanEnrolmentExpected.getYear(), ( (Short) shermanObjects[ 2 ]
).shortValue() );
+ assertTrue( ! ( shermanObjects[ 3 ] instanceof HibernateProxy ) );
+ assertTrue( shermanObjects[ 3 ] instanceof Course );
+ assertEquals( courseExpected, shermanObjects[ 3 ] );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testMultiEntityProjectionList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "e.student" ) )
+ .add( Property.forName( "e.semester" ) )
+ .add( Property.forName( "e.year" ) )
+ .add( Property.forName( "e.course" ) )
+ )
+ .addOrder( Order.asc( "e.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student, e.semester, e.year, e.course from
Enrolment e order by e.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( 4, yogiObjects.length );
+ // TODO: following is initialized for hql and uninitialied for criteria; why?
+ //assertFalse( Hibernate.isInitialized( yogiObjects[ 0 ] ) );
+ //assertFalse( Hibernate.isInitialized( shermanObjects[ 0 ] ) );
+ assertTrue( yogiObjects[ 0 ] instanceof Student );
+ assertTrue( shermanObjects[ 0 ] instanceof Student );
+ assertEquals( yogiEnrolmentExpected.getSemester(), ( (Short) yogiObjects[ 1 ]
).shortValue() );
+ assertEquals( yogiEnrolmentExpected.getYear(), ( (Short) yogiObjects[ 2 ]
).shortValue() );
+ assertEquals( courseExpected, yogiObjects[ 3 ] );
+ assertEquals( shermanEnrolmentExpected.getSemester(), ( (Short) shermanObjects[ 1 ]
).shortValue() );
+ assertEquals( shermanEnrolmentExpected.getYear(), ( (Short) shermanObjects[ 2 ]
).shortValue() );
+ assertTrue( shermanObjects[ 3 ] instanceof Course );
+ assertEquals( courseExpected, shermanObjects[ 3 ] );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiEntityProjectionAliasedList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ // should use PassThroughTransformer by default
+ return s.createCriteria( Enrolment.class, "e" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "e.student" ).as( "st" ) )
+ .add( Property.forName( "e.semester" ).as("sem" ) )
+ .add( Property.forName( "e.year" ).as( "yr" ) )
+ .add( Property.forName( "e.course" ).as( "c" ) )
+ )
+ .addOrder( Order.asc( "e.studentNumber") );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select e.student as st, e.semester as sem, e.year as yr,
e.course as c from Enrolment e order by e.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( 4, yogiObjects.length );
+ // TODO: following is initialized for hql and uninitialied for criteria; why?
+ //assertFalse( Hibernate.isInitialized( yogiObjects[ 0 ] ) );
+ //assertFalse( Hibernate.isInitialized( shermanObjects[ 0 ] ) );
+ assertTrue( yogiObjects[ 0 ] instanceof Student );
+ assertTrue( shermanObjects[ 0 ] instanceof Student );
+ assertEquals( yogiEnrolmentExpected.getSemester(), ( (Short) yogiObjects[ 1 ]
).shortValue() );
+ assertEquals( yogiEnrolmentExpected.getYear(), ( (Short) yogiObjects[ 2 ]
).shortValue() );
+ assertEquals( courseExpected, yogiObjects[ 3 ] );
+ assertEquals( shermanEnrolmentExpected.getSemester(), ( (Short) shermanObjects[ 1 ]
).shortValue() );
+ assertEquals( shermanEnrolmentExpected.getYear(), ( (Short) shermanObjects[ 2 ]
).shortValue() );
+ assertTrue( shermanObjects[ 3 ] instanceof Course );
+ assertEquals( courseExpected, shermanObjects[ 3 ] );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testSingleAggregatedPropProjectionSingleResult() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class )
+ .setProjection( Projections.min( "studentNumber" ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select min( e.studentNumber ) from Enrolment e" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Long );
+ assertEquals( Long.valueOf( yogiExpected.getStudentNumber() ), results );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testMultiAggregatedPropProjectionSingleResult() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class )
+ .setProjection(
+ Projections.projectionList()
+ .add( Projections.min( "studentNumber" ).as(
"minStudentNumber" ) )
+ .add( Projections.max( "studentNumber" ).as(
"maxStudentNumber" ) )
+ );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery(
+ "select min( e.studentNumber ) as minStudentNumber, max( e.studentNumber ) as
maxStudentNumber from Enrolment e" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Object[] );
+ Object[] resultObjects = ( Object[] ) results;
+ assertEquals( Long.valueOf( yogiExpected.getStudentNumber() ), resultObjects[ 0 ] );
+ assertEquals( Long.valueOf( shermanExpected.getStudentNumber() ), resultObjects[ 1 ]
);
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, true );
+ }
+
+ public void testAliasToBeanDtoOneArgList() throws Exception {
+
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .createAlias( "e.student", "st" )
+ .createAlias( "e.course", "co" )
+ .setProjection( Projections.property( "st.name" ).as(
"studentName" ) )
+ .addOrder( Order.asc( "st.studentNumber" ) )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select st.name as studentName from Student st order by
st.studentNumber" )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ StudentDTO dto = ( StudentDTO ) resultList.get( 0 );
+ assertNull( dto.getDescription() );
+ assertEquals( yogiExpected.getName(), dto.getName() );
+ dto = ( StudentDTO ) resultList.get( 1 );
+ assertNull( dto.getDescription() );
+ assertEquals( shermanExpected.getName(), dto.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToBeanDtoMultiArgList() throws Exception {
+
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .createAlias( "e.student", "st" )
+ .createAlias( "e.course", "co" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "st.name" ).as( "studentName" ) )
+ .add( Property.forName( "co.description" ).as(
"courseDescription" ) )
+ )
+ .addOrder( Order.asc( "e.studentNumber" ) )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select st.name as studentName, co.description as
courseDescription from Enrolment e join e.student st join e.course co order by
e.studentNumber" )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ StudentDTO dto = ( StudentDTO ) resultList.get( 0 );
+ assertEquals( courseExpected.getDescription(), dto.getDescription() );
+ assertEquals( yogiExpected.getName(), dto.getName() );
+ dto = ( StudentDTO ) resultList.get( 1 );
+ assertEquals( courseExpected.getDescription(), dto.getDescription() );
+ assertEquals( shermanExpected.getName(), dto.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiProjectionListThenApplyAliasToBean() throws Exception {
+
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .createAlias( "e.student", "st" )
+ .createAlias( "e.course", "co" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "st.name" ) )
+ .add( Property.forName( "co.description" ) )
+ )
+ .addOrder( Order.asc( "e.studentNumber" ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select st.name as studentName, co.description as
courseDescription from Enrolment e join e.student st join e.course co order by
e.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ ResultTransformer transformer = Transformers.aliasToBean( StudentDTO.class );
+ String[] aliases = new String[] { "studentName",
"courseDescription" };
+ for ( int i = 0 ; i < resultList.size(); i++ ) {
+ resultList.set(
+ i,
+ transformer.transformTuple( ( Object[] ) resultList.get( i ), aliases )
+ );
+ }
+
+ assertEquals( 2, resultList.size() );
+ StudentDTO dto = ( StudentDTO ) resultList.get( 0 );
+ assertEquals( courseExpected.getDescription(), dto.getDescription() );
+ assertEquals( yogiExpected.getName(), dto.getName() );
+ dto = ( StudentDTO ) resultList.get( 1 );
+ assertEquals( courseExpected.getDescription(), dto.getDescription() );
+ assertEquals( shermanExpected.getName(), dto.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToBeanDtoLiteralArgList() throws Exception {
+
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .createAlias( "e.student", "st" )
+ .createAlias( "e.course", "co" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "st.name" ).as( "studentName" ) )
+ .add( Projections.sqlProjection(
+ "'lame description' as courseDescription",
+ new String[] { "courseDescription" },
+ new Type[] { Hibernate.STRING }
+ )
+ )
+ )
+ .addOrder( Order.asc( "e.studentNumber" ) )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select st.name as studentName, 'lame description'
as courseDescription from Enrolment e join e.student st join e.course co order by
e.studentNumber" )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ StudentDTO dto = ( StudentDTO ) resultList.get( 0 );
+ assertEquals( "lame description", dto.getDescription() );
+ assertEquals( yogiExpected.getName(), dto.getName() );
+ dto = ( StudentDTO ) resultList.get( 1 );
+ assertEquals( "lame description", dto.getDescription() );
+ assertEquals( shermanExpected.getName(), dto.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testAliasToBeanDtoWithNullAliasList() throws Exception {
+
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Enrolment.class, "e" )
+ .createAlias( "e.student", "st" )
+ .createAlias( "e.course", "co" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "st.name" ).as( "studentName" ) )
+ .add( Property.forName( "st.studentNumber" ) )
+ .add( Property.forName( "co.description" ).as(
"courseDescription" ) )
+ )
+ .addOrder( Order.asc( "e.studentNumber" ) )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select st.name as studentName, co.description as
courseDescription from Enrolment e join e.student st join e.course co order by
e.studentNumber" )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ StudentDTO dto = ( StudentDTO ) resultList.get( 0 );
+ assertEquals( courseExpected.getDescription(), dto.getDescription() );
+ assertEquals( yogiExpected.getName(), dto.getName() );
+ dto = ( StudentDTO ) resultList.get( 1 );
+ assertEquals( courseExpected.getDescription(), dto.getDescription() );
+ assertEquals( shermanExpected.getName(), dto.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testOneSelectNewNoAliasesList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) throws Exception {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection( Projections.property( "s.name" ) )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( new AliasToBeanConstructorResultTransformer( getConstructor()
) );
+ }
+ private Constructor getConstructor() throws NoSuchMethodException {
+ return StudentDTO.class.getConstructor( String.class );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new
org.hibernate.test.querycache.StudentDTO(s.name) from Student s order by
s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ StudentDTO yogi = ( StudentDTO ) resultList.get( 0 );
+ assertNull( yogi.getDescription() );
+ assertEquals( yogiExpected.getName(), yogi.getName() );
+ StudentDTO sherman = ( StudentDTO ) resultList.get( 1 );
+ assertEquals( shermanExpected.getName(), sherman.getName() );
+ assertNull( sherman.getDescription() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testOneSelectNewAliasesList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) throws Exception {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection( Projections.property( "s.name" ).as( "name" ))
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( new AliasToBeanConstructorResultTransformer( getConstructor()
) );
+ }
+ private Constructor getConstructor() throws NoSuchMethodException {
+ return StudentDTO.class.getConstructor( String.class );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new
org.hibernate.test.querycache.StudentDTO(s.name) from Student s order by
s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ StudentDTO yogi = ( StudentDTO ) resultList.get( 0 );
+ assertNull( yogi.getDescription() );
+ assertEquals( yogiExpected.getName(), yogi.getName() );
+ StudentDTO sherman = ( StudentDTO ) resultList.get( 1 );
+ assertEquals( shermanExpected.getName(), sherman.getName() );
+ assertNull( sherman.getDescription() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiSelectNewList() throws Exception{
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) throws Exception {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "s.studentNumber" ).as(
"studentNumber" ))
+ .add( Property.forName( "s.name" ).as( "name" ))
+ )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( new AliasToBeanConstructorResultTransformer( getConstructor()
) );
+ }
+ private Constructor getConstructor() throws NoSuchMethodException {
+ return Student.class.getConstructor( long.class, String.class );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new Student(s.studentNumber, s.name) from Student
s order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Student yogi = ( Student ) resultList.get( 0 );
+ assertEquals( yogiExpected.getStudentNumber(), yogi.getStudentNumber() );
+ assertEquals( yogiExpected.getName(), yogi.getName() );
+ Student sherman = ( Student ) resultList.get( 1 );
+ assertEquals( shermanExpected.getStudentNumber(), sherman.getStudentNumber() );
+ assertEquals( shermanExpected.getName(), sherman.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiSelectNewWithLiteralList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) throws Exception {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Projections.sqlProjection( "555 as studentNumber", new String[]{
"studentNumber" }, new Type[] { Hibernate.LONG } ) )
+ .add( Property.forName( "s.name" ).as( "name" ) )
+ )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( new AliasToBeanConstructorResultTransformer( getConstructor()
) );
+ }
+ private Constructor getConstructor() throws NoSuchMethodException {
+ return Student.class.getConstructor( long.class, String.class );
+ }
+ };
+
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new Student(555L, s.name) from Student s order by
s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Student yogi = ( Student ) resultList.get( 0 );
+ assertEquals( 555L, yogi.getStudentNumber() );
+ assertEquals( yogiExpected.getName(), yogi.getName() );
+ Student sherman = ( Student ) resultList.get( 1 );
+ assertEquals( 555L, sherman.getStudentNumber() );
+ assertEquals( shermanExpected.getName(), sherman.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiSelectNewListList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "s.studentNumber" ).as(
"studentNumber" ))
+ .add( Property.forName( "s.name" ).as( "name" ) )
+ )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( Transformers.TO_LIST );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new list(s.studentNumber, s.name) from Student s
order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ List yogiList = ( List ) resultList.get( 0 );
+ assertEquals( yogiExpected.getStudentNumber(), yogiList.get( 0 ) );
+ assertEquals( yogiExpected.getName(), yogiList.get( 1 ) );
+ List shermanList = ( List ) resultList.get( 1 );
+ assertEquals( shermanExpected.getStudentNumber(), shermanList.get( 0 ) );
+ assertEquals( shermanExpected.getName(), shermanList.get( 1 ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiSelectNewMapUsingAliasesList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "s.studentNumber" ).as( "sNumber" )
)
+ .add( Property.forName( "s.name" ).as( "sName" ) )
+ )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new map(s.studentNumber as sNumber, s.name as
sName) from Student s order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ assertEquals( yogiExpected.getStudentNumber(), yogiMap.get( "sNumber" ) );
+ assertEquals( yogiExpected.getName(), yogiMap.get( "sName" ) );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( shermanExpected.getStudentNumber(), shermanMap.get( "sNumber"
) );
+ assertEquals( shermanExpected.getName(), shermanMap.get( "sName" ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiSelectNewMapUsingAliasesWithFetchJoinList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "pc", Criteria.LEFT_JOIN )
+ .setFetchMode( "enrolments", FetchMode.JOIN )
+ .addOrder( Order.asc( "s.studentNumber" ))
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlSelectNewMapExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new map(s as s, pc as pc) from Student s left join
s.preferredCourse pc left join fetch s.enrolments order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiMap.get( "s" ) );
+ assertEquals( yogiExpected.getPreferredCourse(), yogiMap.get( "pc" ) );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanMap.get( "s" ) );
+ assertNull( shermanMap.get( "pc" ) );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiMap.get( "s" )
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiMap.get( "s"
) ).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanMap.get( "s" )
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanMap.get(
"s" ) ).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlSelectNewMapExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testMultiSelectAliasToEntityMapUsingAliasesWithFetchJoinList() throws
Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .createAlias( "s.preferredCourse", "pc", Criteria.LEFT_JOIN )
+ .setFetchMode( "enrolments", FetchMode.JOIN )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlAliasToEntityMapExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select s as s, pc as pc from Student s left join
s.preferredCourse pc left join fetch s.enrolments order by s.studentNumber" )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ assertEquals( yogiExpected, yogiMap.get( "s" ) );
+ assertEquals(
+ yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Course ) yogiMap.get( "pc" ) ).getCourseCode()
+ );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( shermanExpected, shermanMap.get( "s" ) );
+ assertNull( shermanMap.get( "pc" ) );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertEquals( yogiExpected.getPreferredCourse(), yogiMap.get( "pc" ) );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiMap.get( "s" )
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiMap.get( "s"
) ).getEnrolments() );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) shermanMap.get( "s" )
).getEnrolments() ) );
+ assertEquals( shermanExpected.getEnrolments(), ( ( ( Student ) shermanMap.get(
"s" ) ).getEnrolments() ) );
+ }
+ }
+ };
+ runTest( hqlAliasToEntityMapExecutor, null, checker, false );
+ }
+
+ public void testMultiSelectUsingImplicitJoinWithFetchJoinListHql() throws Exception {
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select s as s, s.preferredCourse as pc from Student s
left join fetch s.enrolments" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ assertTrue( results instanceof Object[] );
+ Object[] yogiObjects = ( Object[] ) results;
+ assertEquals( 2, yogiObjects.length );
+ assertEquals( yogiExpected, yogiObjects[ 0 ] );
+ assertEquals(
+ yogiExpected.getPreferredCourse().getCourseCode(),
+ ( ( Course ) yogiObjects[ 1 ] ).getCourseCode()
+ );
+ if ( areDynamicNonLazyAssociationsChecked() ) {
+ assertEquals( yogiExpected.getPreferredCourse(), yogiObjects[ 1 ] );
+ assertTrue( Hibernate.isInitialized( ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() ) );
+ assertEquals( yogiExpected.getEnrolments(), ( ( Student ) yogiObjects[ 0 ]
).getEnrolments() );
+ }
+ }
+ };
+ runTest( hqlExecutor, null, checker, true );
+ }
+
+ public void testSelectNewMapUsingAliasesList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "s.studentNumber" ).as( "sNumber" )
)
+ .add( Property.forName( "s.name" ).as( "sName" ) )
+ )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new map(s.studentNumber as sNumber, s.name as
sName) from Student s order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Map yogiMap = ( Map ) resultList.get( 0 );
+ assertEquals( yogiExpected.getStudentNumber(), yogiMap.get( "sNumber" ) );
+ assertEquals( yogiExpected.getName(), yogiMap.get( "sName" ) );
+ Map shermanMap = ( Map ) resultList.get( 1 );
+ assertEquals( shermanExpected.getStudentNumber(), shermanMap.get( "sNumber"
) );
+ assertEquals( shermanExpected.getName(), shermanMap.get( "sName" ) );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+ public void testSelectNewEntityConstructorList() throws Exception {
+ CriteriaExecutor criteriaExecutor = new CriteriaExecutor() {
+ protected Criteria getCriteria(Session s) {
+ return s.createCriteria( Student.class, "s" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "s.studentNumber" ).as(
"studentNumber" ) )
+ .add( Property.forName( "s.name" ).as( "name" ) )
+ )
+ .addOrder( Order.asc( "s.studentNumber" ) )
+ .setResultTransformer( new AliasToBeanConstructorResultTransformer( getConstructor()
) );
+ }
+ private Constructor getConstructor() {
+ Type studentNametype =
+ ( ( SessionFactoryImpl ) getSessions() )
+ .getEntityPersister( Student.class.getName() )
+ .getPropertyType( "name" );
+ return ReflectHelper.getConstructor( Student.class, new Type[] { Hibernate.LONG,
studentNametype } );
+ }
+ };
+ HqlExecutor hqlExecutor = new HqlExecutor() {
+ public Query getQuery(Session s) {
+ return s.createQuery( "select new Student(s.studentNumber, s.name) from Student
s order by s.studentNumber" );
+ }
+ };
+ ResultChecker checker = new ResultChecker() {
+ public void check(Object results) {
+ List resultList = ( List ) results;
+ assertEquals( 2, resultList.size() );
+ Student yogi = ( Student ) resultList.get( 0 );
+ assertEquals( yogiExpected.getStudentNumber(), yogi.getStudentNumber() );
+ assertEquals( yogiExpected.getName(), yogi.getName() );
+ Student sherman = ( Student ) resultList.get( 1 );
+ assertEquals( shermanExpected.getStudentNumber(), sherman.getStudentNumber() );
+ assertEquals( shermanExpected.getName(), sherman.getName() );
+ }
+ };
+ runTest( hqlExecutor, criteriaExecutor, checker, false );
+ }
+
+
+
+ protected void runTest(HqlExecutor hqlExecutor, CriteriaExecutor criteriaExecutor,
ResultChecker checker, boolean isSingleResult)
+ throws Exception {
+ createData();
+ try {
+ if ( criteriaExecutor != null ) {
+ runTest( criteriaExecutor, checker, isSingleResult );
+ }
+ if ( hqlExecutor != null ) {
+ runTest( hqlExecutor, checker, isSingleResult );
+ }
+ }
+ finally {
+ deleteData();
+ }
+ }
+
+ private boolean isQueryCacheGetEnabled() {
+ return getQueryCacheMode() == CacheMode.NORMAL ||
+ getQueryCacheMode() == CacheMode.GET;
+ }
+
+ private boolean isQueryCachePutEnabled() {
+ return getQueryCacheMode() == CacheMode.NORMAL ||
+ getQueryCacheMode() == CacheMode.PUT;
+ }
+
+ protected void runTest(QueryExecutor queryExecutor, ResultChecker resultChecker, boolean
isSingleResult) throws Exception{
+ clearCache();
+ clearStatistics();
+
+ Object results = queryExecutor.execute( isSingleResult );
+
+ assertHitCount( 0 );
+ assertMissCount( isQueryCacheGetEnabled() ? 1 : 0 );
+ assertPutCount( isQueryCachePutEnabled() ? 1 : 0 );
+ clearStatistics();
+
+ resultChecker.check( results );
+
+ // check again to make sure nothing got initialized while checking results;
+ assertHitCount( 0 );
+ assertMissCount( 0 );
+ assertPutCount( 0 );
+ clearStatistics();
+
+ results = queryExecutor.execute( isSingleResult );
+
+ assertHitCount( isQueryCacheGetEnabled() ? 1 : 0 );
+ assertMissCount( 0 );
+ assertPutCount( ! isQueryCacheGetEnabled() && isQueryCachePutEnabled() ? 1 : 0
);
+ clearStatistics();
+
+ resultChecker.check( results );
+
+ // check again to make sure nothing got initialized while checking results;
+ assertHitCount( 0 );
+ assertMissCount( 0 );
+ assertPutCount( 0 );
+ clearStatistics();
+ }
+
+ private void multiPropProjectionNoTransformerDynNonLazy(CacheMode sessionCacheMode,
+ boolean isCacheableQuery) {
+ Session s = openSession();
+ s.setCacheMode( sessionCacheMode );
+ Transaction t = s.beginTransaction();
+ List resultList = s.createCriteria( Enrolment.class )
+ .setCacheable( isCacheableQuery )
+ .setFetchMode( "student", FetchMode.JOIN )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "student" ), "student" )
+ .add( Property.forName( "semester" ), "semester" )
+ .add( Property.forName( "year" ), "year" )
+ .add( Property.forName( "course" ), "course" )
+ )
+ .addOrder( Order.asc( "studentNumber") )
+ .list();
+ t.commit();
+ s.close();
+
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( 4, yogiObjects.length );
+ assertTrue( yogiObjects[ 0 ] instanceof Student );
+ assertTrue( Hibernate.isInitialized( yogiObjects[ 0 ] ) );
+ assertEquals( yogiEnrolmentExpected.getSemester(), ( (Short) yogiObjects[ 1 ]
).shortValue() );
+ assertEquals( yogiEnrolmentExpected.getYear(), ( (Short) yogiObjects[ 2 ]
).shortValue() );
+ assertEquals( courseExpected, yogiObjects[ 3 ] );
+ assertTrue( shermanObjects[ 0 ] instanceof Student );
+ assertTrue( Hibernate.isInitialized( shermanObjects[ 0 ] ) );
+ assertEquals( shermanEnrolmentExpected.getSemester(), ( (Short) shermanObjects[ 1 ]
).shortValue() );
+ assertEquals( shermanEnrolmentExpected.getYear(), ( (Short) shermanObjects[ 2 ]
).shortValue() );
+ assertTrue( ! ( shermanObjects[ 3 ] instanceof HibernateProxy ) );
+ assertTrue( shermanObjects[ 3 ] instanceof Course );
+ assertEquals( courseExpected, shermanObjects[ 3 ] );
+ }
+
+/*
+ {
+
+ assertEquals( 2, resultList.size() );
+ Object[] yogiObjects = ( Object[] ) resultList.get( 0 );
+ Object[] shermanObjects = ( Object[] ) resultList.get( 1 );
+ assertEquals( 4, yogiObjects.length );
+ assertEquals( yogiExpected, ( Student ) yogiObjects[ 0 ] );
+ assertEquals( yogiEnrolmentExpected.getSemester(), ( (Short) yogiObjects[ 1 ]
).shortValue() );
+ assertEquals( yogiEnrolmentExpected.getYear(), ( (Short) yogiObjects[ 2 ]
).shortValue() );
+ assertEquals( courseExpected, yogiObjects[ 3 ] );
+ assertEquals( shermanExpected, ( Student ) shermanObjects[ 0 ] );
+ assertEquals( shermanEnrolmentExpected.getSemester(), ( (Short) shermanObjects[ 1 ]
).shortValue() );
+ assertEquals( shermanEnrolmentExpected.getYear(), ( (Short) shermanObjects[ 2 ]
).shortValue() );
+ assertEquals( courseExpected, shermanObjects[ 3 ] );
+
+ }
+
+*/
+/*
+ private void executeProperty() {
+ resultList = s.createCriteria( Student.class )
+ .setCacheable( true )
+ .setProjection(
+ Projections.projectionList()
+ .add( Projections.id().as( "studentNumber" ) )
+ .add( Property.forName( "name" ), "name" )
+ .add( Property.forName( "cityState" ), "cityState" )
+ .add( Property.forName( "preferredCourse" ),
"preferredCourse" )
+ )
+ .list();
+ assertEquals( 2, resultList.size() );
+ for ( Iterator it = resultList.iterator(); it.hasNext(); ) {
+ Object[] objects = ( Object[] ) it.next();
+ assertEquals( 4, objects.length );
+ assertTrue( objects[0] instanceof Long );
+ assertTrue( objects[1] instanceof String );
+ if ( "yogiExpected King".equals( objects[1] ) ) {
+ assertTrue( objects[2] instanceof Name );
+ assertTrue( objects[3] instanceof Course );
+ }
+ else {
+ assertNull( objects[2] );
+ assertNull( objects[3] );
+ }
+ }
+
+ Object[] aResult = ( Object[] ) s.createCriteria( Student.class )
+ .setCacheable( true )
+ .add( Restrictions.idEq( new Long( 667 ) ) )
+ .setProjection(
+ Projections.projectionList()
+ .add( Projections.id().as( "studentNumber" ) )
+ .add( Property.forName( "name" ), "name" )
+ .add( Property.forName( "cityState" ), "cityState" )
+ .add( Property.forName( "preferredCourse" ),
"preferredCourse" )
+ )
+ .uniqueResult();
+ assertNotNull( aResult );
+ assertEquals( 4, aResult.length );
+ assertTrue( aResult[0] instanceof Long );
+ assertTrue( aResult[1] instanceof String );
+ assertTrue( aResult[2] instanceof Name );
+ assertTrue( aResult[3] instanceof Course );
+
+ Long count = ( Long ) s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .setProjection( Property.forName( "studentNumber" ).count().setDistinct()
)
+ .uniqueResult();
+ assertEquals( count, new Long( 2 ) );
+
+ Object object = s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "studentNumber" ).count() )
+ .add( Property.forName( "studentNumber" ).max() )
+ .add( Property.forName( "studentNumber" ).min() )
+ .add( Property.forName( "studentNumber" ).avg() )
+ )
+ .uniqueResult();
+ Object[] result = ( Object[] ) object;
+
+ assertEquals( new Long( 2 ), result[0] );
+ assertEquals( new Long( 667 ), result[1] );
+ assertEquals( new Long( 101 ), result[2] );
+ assertEquals( 384.0, ( ( Double ) result[3] ).doubleValue(), 0.01 );
+
+
+ s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .add( Property.forName( "studentNumber" ).gt( new Long( 665 ) ) )
+ .add( Property.forName( "studentNumber" ).lt( new Long( 668 ) ) )
+ .add( Property.forName( "courseCode" ).like( "HIB",
MatchMode.START ) )
+ .add( Property.forName( "year" ).eq( new Short( ( short ) 1999 ) ) )
+ .addOrder( Property.forName( "studentNumber" ).asc() )
+ .uniqueResult();
+
+ List resultWithMaps = s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "studentNumber" ).as( "stNumber" ) )
+ .add( Property.forName( "courseCode" ).as( "cCode" ) )
+ )
+ .add( Property.forName( "studentNumber" ).gt( new Long( 665 ) ) )
+ .add( Property.forName( "studentNumber" ).lt( new Long( 668 ) ) )
+ .addOrder( Property.forName( "studentNumber" ).asc() )
+ .setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP )
+ .list();
+
+ assertEquals( 1, resultWithMaps.size() );
+ Map m1 = ( Map ) resultWithMaps.get( 0 );
+
+ assertEquals( new Long( 667 ), m1.get( "stNumber" ) );
+ assertEquals( courseExpected.getCourseCode(), m1.get( "cCode" ) );
+
+ resultWithMaps = s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .setProjection( Property.forName( "studentNumber" ).as(
"stNumber" ) )
+ .addOrder( Order.desc( "stNumber" ) )
+ .setResultTransformer( Criteria.ALIAS_TO_ENTITY_MAP )
+ .list();
+
+ assertEquals( 2, resultWithMaps.size() );
+ Map m0 = ( Map ) resultWithMaps.get( 0 );
+ m1 = ( Map ) resultWithMaps.get( 1 );
+
+ assertEquals( new Long( 101 ), m1.get( "stNumber" ) );
+ assertEquals( new Long( 667 ), m0.get( "stNumber" ) );
+
+ List resultWithAliasedBean = s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .createAlias( "student", "st" )
+ .createAlias( "courseExpected", "co" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "st.name" ).as( "studentName" ) )
+ .add( Property.forName( "co.description" ).as(
"courseDescription" ) )
+ )
+ .addOrder( Order.desc( "studentName" ) )
+ .setResultTransformer( Transformers.aliasToBean( StudentDTO.class ) )
+ .list();
+
+ assertEquals( 2, resultWithAliasedBean.size() );
+
+ StudentDTO dto = ( StudentDTO ) resultWithAliasedBean.get( 0 );
+ assertNotNull( dto.getDescription() );
+ assertNotNull( dto.getName() );
+
+ CourseMeeting courseMeetingDto = ( CourseMeeting ) s.createCriteria(
CourseMeeting.class )
+ .setCacheable( true )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "id" ).as( "id" ) )
+ .add( Property.forName( "courseExpected" ).as(
"courseExpected" ) )
+ )
+ .addOrder( Order.desc( "id" ) )
+ .setResultTransformer( Transformers.aliasToBean( CourseMeeting.class ) )
+ .uniqueResult();
+
+ assertNotNull( courseMeetingDto.getId() );
+ assertEquals( courseExpected.getCourseCode(), courseMeetingDto.getId().getCourseCode()
);
+ assertEquals( "Monday", courseMeetingDto.getId().getDay() );
+ assertEquals( "1313 Mockingbird Lane", courseMeetingDto.getId().getLocation()
);
+ assertEquals( 1, courseMeetingDto.getId().getPeriod() );
+ assertEquals( courseExpected.getDescription(),
courseMeetingDto.getCourse().getDescription() );
+
+ s.createCriteria( Student.class )
+ .setCacheable( true )
+ .add( Restrictions.like( "name", "yogiExpected", MatchMode.START
) )
+ .addOrder( Order.asc( "name" ) )
+ .createCriteria( "enrolments", "e" )
+ .addOrder( Order.desc( "year" ) )
+ .addOrder( Order.desc( "semester" ) )
+ .createCriteria( "courseExpected", "c" )
+ .addOrder( Order.asc( "description" ) )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "this.name" ) )
+ .add( Property.forName( "e.year" ) )
+ .add( Property.forName( "e.semester" ) )
+ .add( Property.forName( "c.courseCode" ) )
+ .add( Property.forName( "c.description" ) )
+ )
+ .uniqueResult();
+
+ Projection p1 = Projections.projectionList()
+ .add( Property.forName( "studentNumber" ).count() )
+ .add( Property.forName( "studentNumber" ).max() )
+ .add( Projections.rowCount() );
+
+ Projection p2 = Projections.projectionList()
+ .add( Property.forName( "studentNumber" ).min() )
+ .add( Property.forName( "studentNumber" ).avg() )
+ .add(
+ Projections.sqlProjection(
+ "1 as constOne, count(*) as countStar",
+ new String[] { "constOne", "countStar" },
+ new Type[] { Hibernate.INTEGER, Hibernate.INTEGER }
+ )
+ );
+
+ Object[] array = ( Object[] ) s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .setProjection( Projections.projectionList().add( p1 ).add( p2 ) )
+ .uniqueResult();
+
+ assertEquals( array.length, 7 );
+
+ List list = s.createCriteria( Enrolment.class )
+ .setCacheable( true )
+ .createAlias( "student", "st" )
+ .createAlias( "courseExpected", "co" )
+ .setProjection(
+ Projections.projectionList()
+ .add( Property.forName( "co.courseCode" ).group() )
+ .add( Property.forName( "st.studentNumber" ).count().setDistinct() )
+ .add( Property.forName( "year" ).group() )
+ )
+ .list();
+
+ assertEquals( list.size(), 2 );
+ }
+*/
+ protected void clearCache() {
+ getSessions().evictQueries();
+ }
+
+ protected void clearStatistics() {
+ getSessions().getStatistics().clear();
+ }
+
+ protected void assertEntityFetchCount(int expected) {
+ int actual = ( int ) getSessions().getStatistics().getEntityFetchCount();
+ assertEquals( expected, actual );
+ }
+
+ protected void assertCount(int expected) {
+ int actual = ( int ) getSessions().getStatistics().getQueries().length;
+ assertEquals( expected, actual );
+ }
+
+ protected void assertHitCount(int expected) {
+ int actual = ( int ) getSessions().getStatistics().getQueryCacheHitCount();
+ assertEquals( expected, actual );
+ }
+
+ protected void assertMissCount(int expected) {
+ int actual = ( int ) getSessions().getStatistics().getQueryCacheMissCount();
+ assertEquals( expected, actual );
+ }
+
+ protected void assertPutCount(int expected) {
+ int actual = ( int ) getSessions().getStatistics().getQueryCachePutCount();
+ assertEquals( expected, actual );
+ }
+
+ protected void assertInsertCount(int expected) {
+ int inserts = ( int ) getSessions().getStatistics().getEntityInsertCount();
+ assertEquals( "unexpected insert count", expected, inserts );
+ }
+
+ protected void assertUpdateCount(int expected) {
+ int updates = ( int ) getSessions().getStatistics().getEntityUpdateCount();
+ assertEquals( "unexpected update counts", expected, updates );
+ }
+
+ protected void assertDeleteCount(int expected) {
+ int deletes = ( int ) getSessions().getStatistics().getEntityDeleteCount();
+ assertEquals( "unexpected delete counts", expected, deletes );
+ }
+}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Address.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Address.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Address.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,134 @@
+// $Id: Address.java 7996 2005-08-22 14:49:57Z steveebersole $
+package org.hibernate.test.querycache;
+
+/**
+ * Implementation of Address.
+ *
+ * @author Steve Ebersole
+ */
+public class Address {
+ private long id;
+ private String addressType;
+ private String street;
+ private String city;
+ private String stateProvince;
+ private String postalCode;
+ private String country;
+ private Student student;
+
+ public Address() {}
+
+ public Address(Student student, String type, String street, String city, String
stateProvince, String postalCode, String country) {
+ this.student = student;
+ this.addressType = type;
+ this.street = street;
+ this.city = city;
+ this.stateProvince = stateProvince;
+ this.postalCode = postalCode;
+ this.country = country;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Student getStudent() {
+ return student;
+ }
+
+ public void setStudent(Student student) {
+ this.student = student;
+ }
+
+ public String getAddressType() {
+ return addressType;
+ }
+
+ public void setAddressType(String addressType) {
+ this.addressType = addressType;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getPostalCode() {
+ return postalCode;
+ }
+
+ public void setPostalCode(String postalCode) {
+ this.postalCode = postalCode;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String getStateProvince() {
+ return stateProvince;
+ }
+
+ public void setStateProvince(String stateProvince) {
+ this.stateProvince = stateProvince;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ Address address = ( Address ) o;
+
+ if ( city != null ? !city.equals( address.city ) : address.city != null ) {
+ return false;
+ }
+ if ( country != null ? !country.equals( address.country ) : address.country != null )
{
+ return false;
+ }
+ if ( postalCode != null ? !postalCode.equals( address.postalCode ) : address.postalCode
!= null ) {
+ return false;
+ }
+ if ( stateProvince != null ? !stateProvince.equals( address.stateProvince ) :
address.stateProvince != null ) {
+ return false;
+ }
+ if ( street != null ? !street.equals( address.street ) : address.street != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = street != null ? street.hashCode() : 0;
+ result = 31 * result + ( city != null ? city.hashCode() : 0 );
+ result = 31 * result + ( stateProvince != null ? stateProvince.hashCode() : 0 );
+ result = 31 * result + ( postalCode != null ? postalCode.hashCode() : 0 );
+ result = 31 * result + ( country != null ? country.hashCode() : 0 );
+ return result;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Course.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Course.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Course.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,60 @@
+//$Id: Course.java 5686 2005-02-12 07:27:32Z steveebersole $
+package org.hibernate.test.querycache;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Gavin King
+ */
+public class Course implements Serializable {
+ private String courseCode;
+ private String description;
+ private Set courseMeetings = new HashSet();
+
+ public String getCourseCode() {
+ return courseCode;
+ }
+ public void setCourseCode(String courseCode) {
+ this.courseCode = courseCode;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ public Set getCourseMeetings() {
+ return courseMeetings;
+ }
+ public void setCourseMeetings(Set courseMeetings) {
+ this.courseMeetings = courseMeetings;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || ! ( o instanceof Course ) ) {
+ return false;
+ }
+
+ Course course = ( Course ) o;
+
+ if ( courseCode != null ? !courseCode.equals( course.getCourseCode() ) :
course.getCourseCode() != null ) {
+ return false;
+ }
+ if ( description != null ? !description.equals( course.getDescription() ) :
course.getDescription() != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = courseCode != null ? courseCode.hashCode() : 0;
+ result = 31 * result + ( description != null ? description.hashCode() : 0 );
+ return result;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeeting.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeeting.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeeting.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,55 @@
+package org.hibernate.test.querycache;
+
+/**
+ * @author Gail Badner
+ */
+public class CourseMeeting {
+ private CourseMeetingId id;
+ private Course course;
+
+ public CourseMeeting() {}
+
+ public CourseMeeting(Course course, String day, int period, String location) {
+ this.id = new CourseMeetingId( course, day, period, location );
+ this.course = course;
+ }
+
+ public CourseMeetingId getId() {
+ return id;
+ }
+ public void setId(CourseMeetingId id) {
+ this.id = id;
+ }
+ public Course getCourse() {
+ return course;
+ }
+ public void setCourse(Course course) {
+ this.course = course;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ CourseMeeting that = ( CourseMeeting ) o;
+
+ if ( course != null ? !course.equals( that.course ) : that.course != null ) {
+ return false;
+ }
+ if ( id != null ? !id.equals( that.id ) : that.id != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = id != null ? id.hashCode() : 0;
+ result = 31 * result + ( course != null ? course.hashCode() : 0 );
+ return result;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeetingId.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeetingId.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CourseMeetingId.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,81 @@
+package org.hibernate.test.querycache;
+
+import java.io.Serializable;
+
+/**
+ * @author Gail Badner
+ */
+public class CourseMeetingId implements Serializable {
+ private String courseCode;
+ private String day;
+ private int period;
+ private String location;
+
+ public CourseMeetingId() {}
+
+ public CourseMeetingId(Course course, String day, int period, String location) {
+ this.courseCode = course.getCourseCode();
+ this.day = day;
+ this.period = period;
+ this.location = location;
+ }
+
+ public String getCourseCode() {
+ return courseCode;
+ }
+ public void setCourseCode(String courseCode) {
+ this.courseCode = courseCode;
+ }
+ public String getDay() {
+ return day;
+ }
+ public void setDay(String day) {
+ this.day = day;
+ }
+ public int getPeriod() {
+ return period;
+ }
+ public void setPeriod(int period) {
+ this.period = period;
+ }
+ public String getLocation() {
+ return location;
+ }
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ CourseMeetingId that = ( CourseMeetingId ) o;
+
+ if ( period != that.period ) {
+ return false;
+ }
+ if ( courseCode != null ? !courseCode.equals( that.courseCode ) : that.courseCode !=
null ) {
+ return false;
+ }
+ if ( day != null ? !day.equals( that.day ) : that.day != null ) {
+ return false;
+ }
+ if ( location != null ? !location.equals( that.location ) : that.location != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = courseCode != null ? courseCode.hashCode() : 0;
+ result = 31 * result + ( day != null ? day.hashCode() : 0 );
+ result = 31 * result + period;
+ result = 31 * result + ( location != null ? location.hashCode() : 0 );
+ return result;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheIgnoreResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheIgnoreResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheIgnoreResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,61 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import junit.framework.Test;
+
+import org.hibernate.CacheMode;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * @author Gail Badner
+ */
+public class CriteriaQueryCacheIgnoreResultTransformerTest extends
AbstractQueryCacheResultTransformerTest {
+
+ public CriteriaQueryCacheIgnoreResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
CriteriaQueryCacheIgnoreResultTransformerTest.class );
+ }
+
+ protected CacheMode getQueryCacheMode() {
+ return CacheMode.IGNORE;
+ }
+
+ protected void runTest(HqlExecutor hqlExecutor, CriteriaExecutor criteriaExecutor,
ResultChecker checker, boolean isSingleResult)
+ throws Exception {
+ createData();
+ try {
+ if ( criteriaExecutor != null ) {
+ runTest( criteriaExecutor, checker, isSingleResult );
+ }
+ }
+ finally {
+ deleteData();
+ }
+ }
+}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheNormalResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheNormalResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCacheNormalResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,48 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import junit.framework.Test;
+
+import org.hibernate.CacheMode;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * @author Gail Badner
+ */
+public class CriteriaQueryCacheNormalResultTransformerTest extends
CriteriaQueryCachePutResultTransformerTest {
+
+ public CriteriaQueryCacheNormalResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
CriteriaQueryCacheNormalResultTransformerTest.class );
+ }
+
+ protected CacheMode getQueryCacheMode() {
+ return CacheMode.NORMAL;
+ }
+}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCachePutResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCachePutResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/CriteriaQueryCachePutResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,52 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import junit.framework.Test;
+
+import org.hibernate.CacheMode;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * @author Gail Badner
+ */
+public class CriteriaQueryCachePutResultTransformerTest extends
CriteriaQueryCacheIgnoreResultTransformerTest {
+
+ public CriteriaQueryCachePutResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
CriteriaQueryCachePutResultTransformerTest.class );
+ }
+
+ protected CacheMode getQueryCacheMode() {
+ return CacheMode.PUT;
+ }
+
+ protected boolean areDynamicNonLazyAssociationsChecked() {
+ return false;
+ }
+}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.hbm.xml
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.hbm.xml
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.hbm.xml 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.test.querycache">
+
+ <class name="Course">
+ <id name="courseCode">
+ <generator class="assigned"/>
+ </id>
+ <property name="description"/>
+ <set name="courseMeetings" inverse="true"
cascade="all-delete-orphan" lazy="false">
+ <key column="courseCode"/>
+ <one-to-many class="CourseMeeting"/>
+ </set>
+ </class>
+
+ <class name="CourseMeeting">
+ <composite-id name="id" class="CourseMeetingId">
+ <key-property name="courseCode"/>
+ <key-property name="day"/>
+ <key-property name="period"/>
+ <key-property name="location"/>
+ </composite-id>
+ <many-to-one name="course" insert="false"
update="false" lazy="false">
+ <column name="courseCode"/>
+ </many-to-one>
+ </class>
+
+ <class name="Student">
+ <id name="studentNumber">
+ <column name="studentId"/>
+ <generator class="assigned"/>
+ </id>
+ <property name="name"></property>
+ <!--<component name="name">
+ <property name="first" column="name_first"
not-null="true"/>
+ <property name="middle" column="name_middle"
not-null="false"/>
+ <property name="last" column="name_last"
not-null="true"/>
+ </component>
+ --><set name="enrolments" inverse="true"
cascade="delete">
+ <key column="studentId"/>
+ <one-to-many class="Enrolment"/>
+ </set>
+ <map name="addresses" table="addresses"
cascade="all,delete" lazy="true">
+ <key column="studentNumber"/>
+ <map-key column="addressType" type="string"/>
+ <one-to-many class="Address"/>
+ </map>
+ <many-to-one name="preferredCourse"
column="preferredCourseCode" lazy="proxy"/>
+ <list name="secretCodes" lazy="false">
+ <key>
+ <column name="studentNumber"/>
+ </key>
+ <index column="i"/>
+ <element column="secretCode" type="int"/>
+ </list>
+ </class>
+
+ <class name="Address">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="addressType"/>
+ <property name="street"/>
+ <property name="city"/>
+ <property name="stateProvince"/>
+ <property name="postalCode"/>
+ <property name="country"/>
+ <many-to-one name="student" class="Student"
column="studentNumber" not-null="false"/>
+ </class>
+
+ <class name="Enrolment">
+ <composite-id>
+ <key-property name="studentNumber">
+ <column name="studentId"/>
+ </key-property>
+ <key-property name="courseCode"/>
+ </composite-id>
+ <many-to-one name="student" insert="false"
update="false" lazy="proxy">
+ <column name="studentId"/>
+ </many-to-one>
+ <many-to-one name="course" insert="false"
update="false" lazy="false">
+ <column name="courseCode"/>
+ </many-to-one>
+ <property name="semester" type="short"
not-null="true"/>
+ <property name="year" column="`year`" type="short"
not-null="true"/>
+ </class>
+
+</hibernate-mapping>
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Enrolment.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,87 @@
+//$Id: Enrolment.java 6970 2005-05-31 20:24:41Z oneovthafew $
+package org.hibernate.test.querycache;
+
+import java.io.Serializable;
+
+/**
+ * @author Gavin King
+ */
+public class Enrolment implements Serializable {
+ private Student student;
+ private Course course;
+ private long studentNumber;
+ private String courseCode;
+ private short year;
+ private short semester;
+
+ public String getCourseCode() {
+ return courseCode;
+ }
+ public void setCourseCode(String courseId) {
+ this.courseCode = courseId;
+ }
+ public long getStudentNumber() {
+ return studentNumber;
+ }
+ public void setStudentNumber(long studentId) {
+ this.studentNumber = studentId;
+ }
+ public Course getCourse() {
+ return course;
+ }
+ public void setCourse(Course course) {
+ this.course = course;
+ }
+ public Student getStudent() {
+ return student;
+ }
+ public void setStudent(Student student) {
+ this.student = student;
+ }
+ public short getSemester() {
+ return semester;
+ }
+ public void setSemester(short semester) {
+ this.semester = semester;
+ }
+ public short getYear() {
+ return year;
+ }
+ public void setYear(short year) {
+ this.year = year;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ Enrolment enrolment = ( Enrolment ) o;
+
+ if ( semester != enrolment.semester ) {
+ return false;
+ }
+ if ( studentNumber != enrolment.studentNumber ) {
+ return false;
+ }
+ if ( year != enrolment.year ) {
+ return false;
+ }
+ if ( courseCode != null ? !courseCode.equals( enrolment.courseCode ) :
enrolment.courseCode != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = ( int ) ( studentNumber ^ ( studentNumber >>> 32 ) );
+ result = 31 * result + ( courseCode != null ? courseCode.hashCode() : 0 );
+ result = 31 * result + ( int ) year;
+ result = 31 * result + ( int ) semester;
+ return result;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheIgnoreResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheIgnoreResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheIgnoreResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,87 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import junit.framework.Test;
+
+import org.hibernate.CacheMode;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * @author Gail Badner
+ */
+public class HqlQueryCacheIgnoreResultTransformerTest extends
AbstractQueryCacheResultTransformerTest {
+
+ public HqlQueryCacheIgnoreResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( HqlQueryCacheIgnoreResultTransformerTest.class
);
+ }
+
+ protected CacheMode getQueryCacheMode() {
+ return CacheMode.IGNORE;
+ }
+
+ protected void runTest(HqlExecutor hqlExecutor, CriteriaExecutor criteriaExecutor,
ResultChecker checker, boolean isSingleResult)
+ throws Exception {
+ createData();
+ if ( hqlExecutor != null ) {
+ runTest( hqlExecutor, checker, isSingleResult );
+ }
+ deleteData();
+ }
+
+ public void testAliasToEntityMapNoProjectionList() throws Exception {
+ reportSkip( "known to fail using HQL", "HQL query using
Transformers.ALIAS_TO_ENTITY_MAP with no projection" );
+ }
+ public void testAliasToEntityMapNoProjectionListFailureExpected() throws Exception {
+ super.testAliasToEntityMapNoProjectionList();
+ }
+
+ public void testAliasToEntityMapNoProjectionMultiAndNullList() throws Exception {
+ reportSkip( "known to fail using HQL", "HQL query using
Transformers.ALIAS_TO_ENTITY_MAP with no projection" );
+ }
+ public void testAliasToEntityMapNoProjectionMultiAndNullListFailureExpected() throws
Exception {
+ super.testAliasToEntityMapNoProjectionMultiAndNullList();
+ }
+
+ public void testAliasToEntityMapNoProjectionNullAndNonNullAliasList() throws Exception
{
+ reportSkip( "known to fail using HQL", "HQL query using
Transformers.ALIAS_TO_ENTITY_MAP with no projection" );
+ }
+ public void testAliasToEntityMapNoProjectionNullAndNonNullAliasListFailureExpected()
throws Exception {
+ super.testAliasToEntityMapNoProjectionNullAndNonNullAliasList();
+ }
+
+ // fails due to HHH-3345
+ public void testMultiSelectNewMapUsingAliasesWithFetchJoinList() throws Exception {
+ reportSkip( "known to fail using HQL", "HQL query using 'select
new' and 'join fetch'" );
+ }
+ public void testMultiSelectNewMapUsingAliasesWithFetchJoinListFailureExpected() throws
Exception {
+ super.testMultiSelectNewMapUsingAliasesWithFetchJoinList();
+ }
+
+}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheNormalResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheNormalResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCacheNormalResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,48 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import junit.framework.Test;
+
+import org.hibernate.CacheMode;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * @author Gail Badner
+ */
+public class HqlQueryCacheNormalResultTransformerTest extends
HqlQueryCachePutResultTransformerTest {
+
+ public HqlQueryCacheNormalResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( HqlQueryCacheNormalResultTransformerTest.class
);
+ }
+
+ protected CacheMode getQueryCacheMode() {
+ return CacheMode.NORMAL;
+ }
+}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCachePutResultTransformerTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCachePutResultTransformerTest.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/HqlQueryCachePutResultTransformerTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,53 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.querycache;
+
+import junit.framework.Test;
+
+import org.hibernate.CacheMode;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * @author Gail Badner
+ */
+public class HqlQueryCachePutResultTransformerTest extends
HqlQueryCacheIgnoreResultTransformerTest {
+
+ public HqlQueryCachePutResultTransformerTest(String str) {
+ super( str );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( HqlQueryCachePutResultTransformerTest.class
);
+ }
+
+
+ protected CacheMode getQueryCacheMode() {
+ return CacheMode.PUT;
+ }
+
+ protected boolean areDynamicNonLazyAssociationsChecked() {
+ return false;
+ }
+}
Modified:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java 2010-11-17
10:24:10 UTC (rev 20871)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -42,6 +42,51 @@
public static Test suite() {
return new FunctionalTestClassTestSuite( QueryCacheTest.class );
}
+
+ public void testInvalidationFromBulkHQL() {
+ //
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5426
+
+ getSessions().evictQueries();
+ getSessions().getStatistics().clear();
+
+ Session s = openSession();
+ List list = new ArrayList();
+ s.beginTransaction();
+ for (int i = 0; i < 3; i++) {
+ Item a = new Item();
+ a.setName("a" + i);
+ a.setDescription("a" + i);
+ list.add(a);
+ s.persist(a);
+ }
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ String queryString = "select count(*) from Item";
+ // this query will hit the database and create the cache
+ Long result = (Long) s.createQuery(queryString).setCacheable(true).uniqueResult();
+ assertEquals(3, result.intValue());
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ String updateString = "delete from Item";
+ s.createQuery(updateString).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ // and this one SHOULD not be served by the cache
+ Number result2 = (Number)
s.createQuery(queryString).setCacheable(true).uniqueResult();
+ assertEquals(0, result2.intValue());
+ s.getTransaction().commit();
+ s.close();
+ }
+
//https://jira.jboss.org/jira/browse/JBPAPP-4224
public void testHitCacheInSameSession() {
getSessions().evictQueries();
@@ -224,7 +269,7 @@
getSessions().evictQueries();
getSessions().getStatistics().clear();
- final String queryString = "select i.description from Item i where
i.name='widget'";
+ final String queryString = "select i.description as desc from Item i where
i.name='widget'";
Session s = openSession();
Transaction t = s.beginTransaction();
@@ -239,25 +284,34 @@
QueryStatistics qs = s.getSessionFactory().getStatistics().getQueryStatistics(
queryString );
EntityStatistics es = s.getSessionFactory().getStatistics().getEntityStatistics(
Item.class.getName() );
+ assertEquals( qs.getCacheHitCount(), 0 );
+ assertEquals( qs.getCacheMissCount(), 1 );
+ assertEquals( qs.getCachePutCount(), 1 );
Thread.sleep(200);
s = openSession();
t = s.beginTransaction();
List result = s.createQuery( queryString ).setCacheable(true).list();
assertEquals( result.size(), 1 );
+ assertEquals( i.getDescription(), ( ( String ) result.get( 0 ) ) );
t.commit();
s.close();
assertEquals( qs.getCacheHitCount(), 0 );
+ assertEquals( qs.getCacheMissCount(), 2 );
+ assertEquals( qs.getCachePutCount(), 2 );
s = openSession();
t = s.beginTransaction();
result = s.createQuery( queryString ).setCacheable(true).list();
assertEquals( result.size(), 1 );
+ assertEquals( i.getDescription(), result.get( 0 ) );
t.commit();
s.close();
assertEquals( qs.getCacheHitCount(), 1 );
+ assertEquals( qs.getCacheMissCount(), 2 );
+ assertEquals( qs.getCachePutCount(), 2 );
s = openSession();
t = s.beginTransaction();
@@ -265,10 +319,13 @@
assertEquals( result.size(), 1 );
Map m = (Map) result.get(0);
assertEquals(1, m.size());
+ assertEquals( i.getDescription(), m.get( "desc" ) );
t.commit();
s.close();
- assertEquals( "hit count should not go up since we are adding a
resulttransformer", qs.getCacheHitCount(), 1 );
+ assertEquals( "hit count should go up since data is not transformed until after it
is cached", qs.getCacheHitCount(), 2 );
+ assertEquals( qs.getCacheMissCount(), 2 );
+ assertEquals( qs.getCachePutCount(), 2 );
s = openSession();
t = s.beginTransaction();
@@ -276,10 +333,13 @@
assertEquals( result.size(), 1 );
m = (Map) result.get(0);
assertEquals(1, m.size());
+ assertEquals( i.getDescription(), m.get( "desc" ) );
t.commit();
s.close();
- assertEquals( "hit count should go up since we are using the same
resulttransformer", qs.getCacheHitCount(), 2 );
+ assertEquals( "hit count should go up since data is not transformed until after it
is cachedr", qs.getCacheHitCount(), 3 );
+ assertEquals( qs.getCacheMissCount(), 2 );
+ assertEquals( qs.getCachePutCount(), 2 );
s = openSession();
t = s.beginTransaction();
@@ -292,8 +352,9 @@
t.commit();
s.close();
- assertEquals( qs.getCacheHitCount(), 3 );
- assertEquals( qs.getCacheMissCount(), 3 );
+ assertEquals( qs.getCacheHitCount(), 4 );
+ assertEquals( qs.getCacheMissCount(), 2 );
+ assertEquals( qs.getCachePutCount(), 2 );
Thread.sleep(200);
@@ -304,14 +365,18 @@
i = (Item) s.get( Item.class, new Long(i.getId()) );
assertEquals( (String) result.get(0), "A middle-quality widget." );
+ assertEquals( qs.getCacheHitCount(), 4 );
+ assertEquals( qs.getCacheMissCount(), 3 );
+ assertEquals( qs.getCachePutCount(), 3 );
+
s.delete(i);
t.commit();
s.close();
- assertEquals( qs.getCacheHitCount(), 3 );
- assertEquals( qs.getCacheMissCount(), 4 );
- assertEquals( qs.getCachePutCount(), 4 );
- assertEquals( qs.getExecutionCount(), 4 );
+ assertEquals( qs.getCacheHitCount(), 4 );
+ assertEquals( qs.getCacheMissCount(), 3 );
+ assertEquals( qs.getCachePutCount(), 3 );
+ assertEquals( qs.getExecutionCount(), 3 );
assertEquals( es.getFetchCount(), 0 ); //check that it was being cached
}
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Student.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Student.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/Student.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,102 @@
+//$Id: Student.java 9116 2006-01-23 21:21:01Z steveebersole $
+package org.hibernate.test.querycache;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Gavin King
+ */
+public class Student {
+ private long studentNumber;
+ private String name;
+ private Course preferredCourse;
+ private Set enrolments = new HashSet();
+ private Map addresses = new HashMap();
+ private List secretCodes = new ArrayList();
+
+ public Student() {}
+
+ public Student(long studentNumber, String name) {
+ this.studentNumber = studentNumber;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getStudentNumber() {
+ return studentNumber;
+ }
+
+ public void setStudentNumber(long studentNumber) {
+ this.studentNumber = studentNumber;
+ }
+
+ public Map getAddresses() {
+ return addresses;
+ }
+
+ public void setAddresses(Map addresses) {
+ this.addresses = addresses;
+ }
+
+ public Course getPreferredCourse() {
+ return preferredCourse;
+ }
+
+ public void setPreferredCourse(Course preferredCourse) {
+ this.preferredCourse = preferredCourse;
+ }
+
+ public Set getEnrolments() {
+ return enrolments;
+ }
+
+ public void setEnrolments(Set employments) {
+ this.enrolments = employments;
+ }
+
+ public List getSecretCodes() {
+ return secretCodes;
+ }
+
+ public void setSecretCodes(List secretCodes) {
+ this.secretCodes = secretCodes;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || ! ( o instanceof Student ) ) {
+ return false;
+ }
+
+ Student student = ( Student ) o;
+
+ if ( studentNumber != student.getStudentNumber() ) {
+ return false;
+ }
+ if ( name != null ? !name.equals( student.getName() ) : student.getName() != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = ( int ) ( studentNumber ^ ( studentNumber >>> 32 ) );
+ result = 31 * result + ( name != null ? name.hashCode() : 0 );
+ return result;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/StudentDTO.java
===================================================================
---
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/StudentDTO.java
(rev 0)
+++
core/branches/Branch_3_3_2_GA_CP/testsuite/src/test/java/org/hibernate/test/querycache/StudentDTO.java 2010-11-29
07:23:24 UTC (rev 20872)
@@ -0,0 +1,60 @@
+/*
+ * Created on 28-Jan-2005
+ *
+ */
+package org.hibernate.test.querycache;
+
+/**
+ * @author max
+ *
+ */
+public class StudentDTO {
+
+ private String studentName;
+ private String courseDescription;
+
+ public StudentDTO() { }
+
+ public StudentDTO(String name) {
+ this.studentName = name;
+ }
+
+ public StudentDTO(String name, String description) {
+ this.studentName = name;
+ this.courseDescription = description;
+ }
+
+ public String getName() {
+ return studentName;
+ }
+
+ public String getDescription() {
+ return courseDescription;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ StudentDTO that = ( StudentDTO ) o;
+
+ if ( courseDescription != null ? !courseDescription.equals( that.courseDescription ) :
that.courseDescription != null ) {
+ return false;
+ }
+ if ( studentName != null ? !studentName.equals( that.studentName ) : that.studentName
!= null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = studentName != null ? studentName.hashCode() : 0;
+ result = 31 * result + ( courseDescription != null ? courseDescription.hashCode() : 0
);
+ return result;
+ }
+}
\ No newline at end of file