HHH-5645 - Criteria.createAlias with specified criterion results in wrong parameters passed into SQL statement
This commit is contained in:
parent
eaeda2f41d
commit
dbd5f81f79
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.loader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
@ -24,6 +26,7 @@ import org.hibernate.type.EntityType;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public abstract class OuterJoinLoader extends BasicLoader {
|
||||
|
||||
protected Loadable[] persisters;
|
||||
protected CollectionPersister[] collectionPersisters;
|
||||
protected int[] collectionOwners;
|
||||
|
@ -35,12 +38,13 @@ public abstract class OuterJoinLoader extends BasicLoader {
|
|||
protected String sql;
|
||||
protected String[] suffixes;
|
||||
protected String[] collectionSuffixes;
|
||||
protected List associations;
|
||||
|
||||
private LoadQueryInfluencers loadQueryInfluencers;
|
||||
private LoadQueryInfluencers loadQueryInfluencers;
|
||||
|
||||
protected final Dialect getDialect() {
|
||||
return getFactory().getDialect();
|
||||
}
|
||||
return getFactory().getDialect();
|
||||
}
|
||||
|
||||
public OuterJoinLoader(
|
||||
SessionFactoryImplementor factory,
|
||||
|
@ -110,6 +114,7 @@ public abstract class OuterJoinLoader extends BasicLoader {
|
|||
collectionOwners = walker.getCollectionOwners();
|
||||
sql = walker.getSQLString();
|
||||
aliases = walker.getAliases();
|
||||
associations = walker.getAssociations();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.io.Serializable;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -28,6 +29,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.internal.CriteriaImpl;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.loader.OuterJoinLoader;
|
||||
import org.hibernate.loader.OuterJoinableAssociation;
|
||||
import org.hibernate.loader.spi.AfterLoadAction;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
|
@ -44,8 +46,8 @@ import org.hibernate.type.Type;
|
|||
*/
|
||||
public class CriteriaLoader extends OuterJoinLoader {
|
||||
|
||||
//TODO: this class depends directly upon CriteriaImpl,
|
||||
// in the impl package ... add a CriteriaImplementor
|
||||
//TODO: this class depends directly upon CriteriaImpl,
|
||||
// in the impl package ... add a CriteriaImplementor
|
||||
// interface
|
||||
|
||||
//NOTE: unlike all other Loaders, this one is NOT
|
||||
|
@ -73,7 +75,7 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
criteria,
|
||||
rootEntityName,
|
||||
CriteriaQueryTranslator.ROOT_SQL_ALIAS
|
||||
);
|
||||
);
|
||||
|
||||
querySpaces = translator.getQuerySpaces();
|
||||
|
||||
|
@ -84,10 +86,11 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
criteria,
|
||||
rootEntityName,
|
||||
loadQueryInfluencers
|
||||
);
|
||||
);
|
||||
|
||||
initFromWalker( walker );
|
||||
initFromWalker(walker);
|
||||
|
||||
translator.setAssociations(getAssociationPaths());
|
||||
userAliases = walker.getUserAliases();
|
||||
resultTypes = walker.getResultTypes();
|
||||
includeInResultRow = walker.includeInResultRow();
|
||||
|
@ -97,15 +100,28 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
|
||||
}
|
||||
|
||||
private Set<String> getAssociationPaths() {
|
||||
Set<String> associationPaths = new HashSet<>();
|
||||
for ( Object association : this.associations ) {
|
||||
if ( association instanceof OuterJoinableAssociation ) {
|
||||
OuterJoinableAssociation outerJoinableAssociation = (OuterJoinableAssociation) association;
|
||||
if ( outerJoinableAssociation.getPropertyPath() != null ) {
|
||||
associationPaths.add( outerJoinableAssociation.getPropertyPath().getFullPath() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return associationPaths;
|
||||
}
|
||||
|
||||
public ScrollableResultsImplementor scroll(SharedSessionContractImplementor session, ScrollMode scrollMode)
|
||||
throws HibernateException {
|
||||
throws HibernateException {
|
||||
QueryParameters qp = translator.getQueryParameters();
|
||||
qp.setScrollMode( scrollMode );
|
||||
return scroll( qp, resultTypes, null, session );
|
||||
qp.setScrollMode(scrollMode);
|
||||
return scroll(qp, resultTypes, null, session);
|
||||
}
|
||||
|
||||
public List list(SharedSessionContractImplementor session)
|
||||
throws HibernateException {
|
||||
throws HibernateException {
|
||||
return list( session, translator.getQueryParameters(), querySpaces, resultTypes );
|
||||
|
||||
}
|
||||
|
@ -136,9 +152,9 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
ResultTransformer transformer,
|
||||
ResultSet rs,
|
||||
SharedSessionContractImplementor session)
|
||||
throws SQLException, HibernateException {
|
||||
throws SQLException, HibernateException {
|
||||
return resolveResultTransformer( transformer ).transformTuple(
|
||||
getResultRow( row, rs, session ),
|
||||
getResultRow( row, rs, session),
|
||||
getResultRowAliases()
|
||||
);
|
||||
}
|
||||
|
@ -151,14 +167,14 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
Type[] types = translator.getProjectedTypes();
|
||||
result = new Object[types.length];
|
||||
String[] columnAliases = translator.getProjectedColumnAliases();
|
||||
for ( int i = 0, pos = 0; i < result.length; i++ ) {
|
||||
for ( int i=0, pos=0; i<result.length; i++ ) {
|
||||
int numColumns = types[i].getColumnSpan( session.getFactory() );
|
||||
if ( numColumns > 1 ) {
|
||||
String[] typeColumnAliases = ArrayHelper.slice( columnAliases, pos, numColumns );
|
||||
result[i] = types[i].nullSafeGet( rs, typeColumnAliases, session, null );
|
||||
String[] typeColumnAliases = ArrayHelper.slice( columnAliases, pos, numColumns );
|
||||
result[i] = types[i].nullSafeGet(rs, typeColumnAliases, session, null);
|
||||
}
|
||||
else {
|
||||
result[i] = types[i].nullSafeGet( rs, columnAliases[pos], session, null );
|
||||
result[i] = types[i].nullSafeGet(rs, columnAliases[pos], session, null);
|
||||
}
|
||||
pos += numColumns;
|
||||
}
|
||||
|
@ -174,7 +190,7 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
return row;
|
||||
}
|
||||
else {
|
||||
Object[] result = new Object[resultRowLength];
|
||||
Object[] result = new Object[ resultRowLength ];
|
||||
int j = 0;
|
||||
for ( int i = 0; i < row.length; i++ ) {
|
||||
if ( includeInResultRow[i] ) {
|
||||
|
@ -207,8 +223,8 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
|
||||
if ( ( parameters.getLockOptions().getFollowOnLocking() == null && dialect.useFollowOnLocking( parameters ) ) ||
|
||||
( parameters.getLockOptions().getFollowOnLocking() != null && parameters.getLockOptions().getFollowOnLocking() ) ) {
|
||||
final LockMode lockMode = determineFollowOnLockMode( lockOptions );
|
||||
if ( lockMode != LockMode.UPGRADE_SKIPLOCKED ) {
|
||||
final LockMode lockMode = determineFollowOnLockMode( lockOptions );
|
||||
if( lockMode != LockMode.UPGRADE_SKIPLOCKED ) {
|
||||
// Dialect prefers to perform locking in a separate step
|
||||
LOG.usingFollowOnLocking();
|
||||
|
||||
|
@ -218,27 +234,27 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
|
||||
afterLoadActions.add(
|
||||
new AfterLoadAction() {
|
||||
@Override
|
||||
@Override
|
||||
public void afterLoad(SharedSessionContractImplementor session, Object entity, Loadable persister) {
|
||||
( (Session) session ).buildLockRequest( lockOptionsToUse )
|
||||
( (Session) session ).buildLockRequest( lockOptionsToUse )
|
||||
.lock( persister.getEntityName(), entity );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
parameters.setLockOptions( new LockOptions() );
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
|
||||
locks.setScope( lockOptions.getScope() );
|
||||
locks.setTimeOut( lockOptions.getTimeOut() );
|
||||
final LockOptions locks = new LockOptions(lockOptions.getLockMode());
|
||||
locks.setScope( lockOptions.getScope());
|
||||
locks.setTimeOut( lockOptions.getTimeOut());
|
||||
|
||||
final Map<String,String[]> keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null;
|
||||
final String[] drivingSqlAliases = getAliases();
|
||||
for ( int i = 0; i < drivingSqlAliases.length; i++ ) {
|
||||
final LockMode lockMode = lockOptions.getAliasSpecificLockMode( drivingSqlAliases[i] );
|
||||
if ( lockMode != null ) {
|
||||
final Lockable drivingPersister = (Lockable) getEntityPersisters()[i];
|
||||
final Lockable drivingPersister = ( Lockable ) getEntityPersisters()[i];
|
||||
final String rootSqlAlias = drivingPersister.getRootTableAlias( drivingSqlAliases[i] );
|
||||
locks.setAliasSpecificLockMode( rootSqlAlias, lockMode );
|
||||
if ( keyColumnNames != null ) {
|
||||
|
@ -270,9 +286,9 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
}
|
||||
final int size = entityAliases.length;
|
||||
LockMode[] lockModesArray = new LockMode[size];
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
for ( int i=0; i<size; i++ ) {
|
||||
LockMode lockMode = lockOptions.getAliasSpecificLockMode( entityAliases[i] );
|
||||
lockModesArray[i] = lockMode == null ? lockOptions.getLockMode() : lockMode;
|
||||
lockModesArray[i] = lockMode==null ? lockOptions.getLockMode() : lockMode;
|
||||
}
|
||||
return lockModesArray;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,12 @@ package org.hibernate.loader.criteria;
|
|||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -63,38 +65,43 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
private final Map<Criteria, String> criteriaSQLAliasMap = new HashMap<Criteria, String>();
|
||||
private final Map<String, Criteria> aliasCriteriaMap = new HashMap<String, Criteria>();
|
||||
private final Map<String, Criteria> associationPathCriteriaMap = new LinkedHashMap<String, Criteria>();
|
||||
private final Map<String, JoinType> associationPathJoinTypesMap = new LinkedHashMap<String, JoinType>();
|
||||
private final Map<String, JoinType> associationPathJoinTypesMap = new LinkedHashMap<String,JoinType>();
|
||||
private final Map<String, Criterion> withClauseMap = new HashMap<String, Criterion>();
|
||||
private Set<String> associations;
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final SessionFactoryHelper helper;
|
||||
|
||||
public CriteriaQueryTranslator(
|
||||
final SessionFactoryImplementor factory,
|
||||
final CriteriaImpl criteria,
|
||||
final String rootEntityName,
|
||||
final String rootSQLAlias,
|
||||
CriteriaQuery outerQuery) throws HibernateException {
|
||||
final CriteriaImpl criteria,
|
||||
final String rootEntityName,
|
||||
final String rootSQLAlias,
|
||||
CriteriaQuery outerQuery) throws HibernateException {
|
||||
this( factory, criteria, rootEntityName, rootSQLAlias );
|
||||
outerQueryTranslator = outerQuery;
|
||||
}
|
||||
|
||||
public CriteriaQueryTranslator(
|
||||
final SessionFactoryImplementor factory,
|
||||
final CriteriaImpl criteria,
|
||||
final String rootEntityName,
|
||||
final String rootSQLAlias) throws HibernateException {
|
||||
final CriteriaImpl criteria,
|
||||
final String rootEntityName,
|
||||
final String rootSQLAlias) throws HibernateException {
|
||||
this.rootCriteria = criteria;
|
||||
this.rootEntityName = rootEntityName;
|
||||
this.sessionFactory = factory;
|
||||
this.rootSQLAlias = rootSQLAlias;
|
||||
this.helper = new SessionFactoryHelper( factory );
|
||||
this.helper = new SessionFactoryHelper(factory);
|
||||
createAliasCriteriaMap();
|
||||
createAssociationPathCriteriaMap();
|
||||
createCriteriaEntityNameMap();
|
||||
createCriteriaSQLAliasMap();
|
||||
}
|
||||
|
||||
public void setAssociations(Set<String> associations) {
|
||||
this.associations = associations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSQLAlias() {
|
||||
int aliasCount = 0;
|
||||
|
@ -195,7 +202,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
}
|
||||
else {
|
||||
// otherwise, recurse
|
||||
return getWholeAssociationPath( (CriteriaImpl.Subcriteria) parent ) + '.' + path;
|
||||
return getWholeAssociationPath( ( CriteriaImpl.Subcriteria ) parent ) + '.' + path;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +211,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
final CriteriaInfoProvider rootProvider = new EntityCriteriaInfoProvider(
|
||||
(Queryable) sessionFactory.getEntityPersister( rootEntityName )
|
||||
);
|
||||
criteriaInfoMap.put( rootCriteria, rootProvider );
|
||||
criteriaInfoMap.put( rootCriteria, rootProvider);
|
||||
nameCriteriaInfoMap.put( rootProvider.getName(), rootProvider );
|
||||
|
||||
for ( final String key : associationPathCriteriaMap.keySet() ) {
|
||||
|
@ -229,11 +236,11 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
if ( type.isAssociationType() ) {
|
||||
// CollectionTypes are always also AssociationTypes - but there's not always an associated entity...
|
||||
final AssociationType atype = (AssociationType) type;
|
||||
final CollectionType ctype = type.isCollectionType() ? (CollectionType) type : null;
|
||||
final Type elementType = ( ctype != null ) ? ctype.getElementType( sessionFactory ) : null;
|
||||
final CollectionType ctype = type.isCollectionType() ? (CollectionType)type : null;
|
||||
final Type elementType = (ctype != null) ? ctype.getElementType( sessionFactory ) : null;
|
||||
// is the association a collection of components or value-types? (i.e a colloction of valued types?)
|
||||
if ( ctype != null && elementType.isComponentType() ) {
|
||||
provider = new ComponentCollectionCriteriaInfoProvider( helper.getCollectionPersister( ctype.getRole() ) );
|
||||
if ( ctype != null && elementType.isComponentType() ) {
|
||||
provider = new ComponentCollectionCriteriaInfoProvider( helper.getCollectionPersister(ctype.getRole()) );
|
||||
}
|
||||
else if ( ctype != null && !elementType.isEntityType() ) {
|
||||
provider = new ScalarCollectionCriteriaInfoProvider( helper, ctype.getRole() );
|
||||
|
@ -247,7 +254,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
componentPath = "";
|
||||
}
|
||||
else if ( type.isComponentType() ) {
|
||||
if ( !tokens.hasMoreTokens() ) {
|
||||
if (!tokens.hasMoreTokens()) {
|
||||
throw new QueryException(
|
||||
"Criteria objects cannot be created directly on components. Create a criteria on " +
|
||||
"owning entity and use a dotted property to access component property: " + path
|
||||
|
@ -271,7 +278,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
|
||||
private void createCriteriaSQLAliasMap() {
|
||||
int i = 0;
|
||||
for ( final Criteria crit : criteriaInfoMap.keySet() ) {
|
||||
for(final Criteria crit : criteriaInfoMap.keySet()){
|
||||
final CriteriaInfoProvider value = criteriaInfoMap.get( crit );
|
||||
String alias = crit.getAlias();
|
||||
if ( alias == null ) {
|
||||
|
@ -304,6 +311,9 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
|
||||
final List<Object> values = new ArrayList<Object>();
|
||||
final List<Type> types = new ArrayList<Type>();
|
||||
final Map<String, String> aliasMap = new HashMap<String, String>();
|
||||
final Map<String, Collection<Object>> valueMap = new HashMap<String, Collection<Object>>();
|
||||
final Map<String, Collection<Type>> typeMap = new HashMap<String, Collection<Type>>();
|
||||
final Iterator<CriteriaImpl.Subcriteria> subcriteriaIterator = rootCriteria.iterateSubcriteria();
|
||||
while ( subcriteriaIterator.hasNext() ) {
|
||||
final CriteriaImpl.Subcriteria subcriteria = subcriteriaIterator.next();
|
||||
|
@ -311,11 +321,65 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
if ( lm != null ) {
|
||||
lockOptions.setAliasSpecificLockMode( getSQLAlias( subcriteria ), lm );
|
||||
}
|
||||
aliasMap.put(subcriteria.getPath(), subcriteria.getAlias());
|
||||
if ( subcriteria.getWithClause() != null ) {
|
||||
final TypedValue[] tv = subcriteria.getWithClause().getTypedValues( subcriteria, this );
|
||||
for ( TypedValue aTv : tv ) {
|
||||
values.add( aTv.getValue() );
|
||||
types.add( aTv.getType() );
|
||||
Collection<Object> valueCollection = valueMap.get( subcriteria.getPath() );
|
||||
Collection<Type> typeCollection = typeMap.get( subcriteria.getPath() );
|
||||
if ( valueCollection == null ) {
|
||||
valueCollection = new LinkedList<>();
|
||||
valueMap.put( subcriteria.getPath(), valueCollection );
|
||||
}
|
||||
if ( typeCollection == null ) {
|
||||
typeCollection = new LinkedList<>();
|
||||
typeMap.put( subcriteria.getPath(), typeCollection );
|
||||
}
|
||||
valueCollection.add( aTv.getValue() );
|
||||
typeCollection.add( aTv.getType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( associations != null ) {
|
||||
for ( String association : this.associations ) {
|
||||
if ( association.contains( "." ) ) {
|
||||
String alias = null;
|
||||
String[] pathArray = association.split( "\\." );
|
||||
for ( int i = 0; i < pathArray.length; i++ ) {
|
||||
String element = pathArray[i];
|
||||
if ( i == ( pathArray.length - 1 ) ) {
|
||||
Collection<Object> valueList = valueMap.get( alias + "." + element );
|
||||
Collection<Type> typeList = typeMap.get( alias + "." + element );
|
||||
if ( typeList != null ) {
|
||||
values.addAll( valueList );
|
||||
types.addAll( typeList );
|
||||
}
|
||||
}
|
||||
else if ( alias == null ) {
|
||||
alias = aliasMap.get( element );
|
||||
}
|
||||
else {
|
||||
alias = aliasMap.get( alias + "." + element );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
String matchingAssociation = null;
|
||||
for ( Map.Entry<String, Collection<Type>> typeEntry : typeMap.entrySet() ) {
|
||||
String path = typeEntry.getKey();
|
||||
if ( path.equals( association ) || path.endsWith( "." + association ) ) {
|
||||
matchingAssociation = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( matchingAssociation != null ) {
|
||||
Collection<Object> valueList = valueMap.get( matchingAssociation );
|
||||
Collection<Type> typeList = typeMap.get( matchingAssociation );
|
||||
if ( typeList != null ) {
|
||||
values.addAll( valueList );
|
||||
types.addAll( typeList );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,17 +401,17 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
final Type[] typeArray = ArrayHelper.toTypeArray( types );
|
||||
return new QueryParameters(
|
||||
typeArray,
|
||||
valueArray,
|
||||
lockOptions,
|
||||
selection,
|
||||
rootCriteria.isReadOnlyInitialized(),
|
||||
( rootCriteria.isReadOnlyInitialized() && rootCriteria.isReadOnly() ),
|
||||
rootCriteria.getCacheable(),
|
||||
rootCriteria.getCacheRegion(),
|
||||
rootCriteria.getComment(),
|
||||
rootCriteria.getQueryHints(),
|
||||
rootCriteria.isLookupByNaturalKey(),
|
||||
rootCriteria.getResultTransformer()
|
||||
valueArray,
|
||||
lockOptions,
|
||||
selection,
|
||||
rootCriteria.isReadOnlyInitialized(),
|
||||
( rootCriteria.isReadOnlyInitialized() && rootCriteria.isReadOnly() ),
|
||||
rootCriteria.getCacheable(),
|
||||
rootCriteria.getCacheRegion(),
|
||||
rootCriteria.getComment(),
|
||||
rootCriteria.getQueryHints(),
|
||||
rootCriteria.isLookupByNaturalKey(),
|
||||
rootCriteria.getResultTransformer()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -368,8 +432,8 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
public String getSelect() {
|
||||
return rootCriteria.getProjection().toSqlString(
|
||||
rootCriteria.getProjectionCriteria(),
|
||||
0,
|
||||
this
|
||||
0,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -384,7 +448,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
|
||||
public String[] getProjectedColumnAliases() {
|
||||
return rootCriteria.getProjection() instanceof EnhancedProjection ?
|
||||
( (EnhancedProjection) rootCriteria.getProjection() ).getColumnAliases( 0, rootCriteria, this ) :
|
||||
( ( EnhancedProjection ) rootCriteria.getProjection() ).getColumnAliases( 0, rootCriteria, this ) :
|
||||
rootCriteria.getProjection().getColumnAliases( 0 );
|
||||
}
|
||||
|
||||
|
@ -451,14 +515,14 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
@Override
|
||||
public String[] getColumnsUsingProjection(
|
||||
Criteria subcriteria,
|
||||
String propertyName) throws HibernateException {
|
||||
String propertyName) throws HibernateException {
|
||||
|
||||
//first look for a reference to a projection alias
|
||||
final Projection projection = rootCriteria.getProjection();
|
||||
String[] projectionColumns = null;
|
||||
if ( projection != null ) {
|
||||
projectionColumns = ( projection instanceof EnhancedProjection ?
|
||||
( (EnhancedProjection) projection ).getColumnAliases( propertyName, 0, rootCriteria, this ) :
|
||||
( ( EnhancedProjection ) projection ).getColumnAliases( propertyName, 0, rootCriteria, this ) :
|
||||
projection.getColumnAliases( propertyName, 0 )
|
||||
);
|
||||
}
|
||||
|
@ -468,7 +532,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
try {
|
||||
return getColumns( propertyName, subcriteria );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
catch ( HibernateException he ) {
|
||||
//not found in inner query , try the outer query
|
||||
if ( outerQueryTranslator != null ) {
|
||||
return outerQueryTranslator.getColumnsUsingProjection( subcriteria, propertyName );
|
||||
|
@ -487,29 +551,29 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
@Override
|
||||
public String[] getIdentifierColumns(Criteria criteria) {
|
||||
String[] idcols =
|
||||
( (Loadable) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierColumnNames();
|
||||
( ( Loadable ) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierColumnNames();
|
||||
return StringHelper.qualify( getSQLAlias( criteria ), idcols );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getIdentifierType(Criteria criteria) {
|
||||
return ( (Loadable) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierType();
|
||||
return ( ( Loadable ) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue getTypedIdentifierValue(Criteria criteria, Object value) {
|
||||
final Loadable loadable = (Loadable) getPropertyMapping( getEntityName( criteria ) );
|
||||
final Loadable loadable = ( Loadable ) getPropertyMapping( getEntityName( criteria ) );
|
||||
return new TypedValue( loadable.getIdentifierType(), value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumns(
|
||||
String propertyName,
|
||||
Criteria subcriteria) throws HibernateException {
|
||||
Criteria subcriteria) throws HibernateException {
|
||||
return getPropertyMapping( getEntityName( subcriteria, propertyName ) )
|
||||
.toColumns(
|
||||
getSQLAlias( subcriteria, propertyName ),
|
||||
getPropertyName( propertyName )
|
||||
getPropertyName( propertyName )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -519,12 +583,12 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
* Projection aliases are ignored.
|
||||
*/
|
||||
@Override
|
||||
public String[] findColumns(String propertyName, Criteria subcriteria)
|
||||
throws HibernateException {
|
||||
public String[] findColumns(String propertyName, Criteria subcriteria )
|
||||
throws HibernateException {
|
||||
try {
|
||||
return getColumns( propertyName, subcriteria );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
catch ( HibernateException he ) {
|
||||
//not found in inner query, try the outer query
|
||||
if ( outerQueryTranslator != null ) {
|
||||
return outerQueryTranslator.findColumns( propertyName, subcriteria );
|
||||
|
@ -542,8 +606,8 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
//first look for a reference to a projection alias
|
||||
final Projection projection = rootCriteria.getProjection();
|
||||
Type[] projectionTypes = projection == null ?
|
||||
null :
|
||||
projection.getTypes( propertyName, subcriteria, this );
|
||||
null :
|
||||
projection.getTypes( propertyName, subcriteria, this );
|
||||
|
||||
if ( projectionTypes == null ) {
|
||||
try {
|
||||
|
@ -551,7 +615,7 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
//look for a property
|
||||
return getType( subcriteria, propertyName );
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
catch ( HibernateException he ) {
|
||||
//not found in inner query , try the outer query
|
||||
if ( outerQueryTranslator != null ) {
|
||||
return outerQueryTranslator.getType( subcriteria, propertyName );
|
||||
|
@ -666,5 +730,4 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
|
|||
final CriteriaImpl.Subcriteria subcriteria = (CriteriaImpl.Subcriteria) getCriteria( path );
|
||||
return subcriteria != null && subcriteria.hasRestriction();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.query.criteria.internal;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.CriteriaSpecification;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.criterion.ProjectionList;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.sql.JoinType;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class AliasWithCriterionTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testCaseClause() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Criteria criteria = session.createCriteria( TableA.class );
|
||||
|
||||
final String TABLE_B_ALIAS = "tableBAlias";
|
||||
final String TABLE_C_ALIAS = "tableCAlias";
|
||||
|
||||
Criterion tableCRestriction = Restrictions.eq( TABLE_C_ALIAS + ".tableCBoolean", false );
|
||||
criteria.createAlias(
|
||||
TABLE_B_ALIAS + ".tableCs",
|
||||
TABLE_C_ALIAS,
|
||||
JoinType.LEFT_OUTER_JOIN,
|
||||
tableCRestriction
|
||||
);
|
||||
|
||||
Criterion tableBRestriction = Restrictions.eq( TABLE_B_ALIAS + ".tableBDate", new Date() );
|
||||
criteria.createAlias( "tableBs", TABLE_B_ALIAS, JoinType.LEFT_OUTER_JOIN, tableBRestriction );
|
||||
|
||||
criteria.add( Restrictions.eq( "tableACharacter", "c" ) );
|
||||
|
||||
ProjectionList projectionList = Projections.projectionList();
|
||||
projectionList.add( Projections.property( "tableACharacter" ) );
|
||||
criteria.setProjection( projectionList );
|
||||
|
||||
criteria.list();
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
TableA.class,
|
||||
TableB.class,
|
||||
TableC.class,
|
||||
};
|
||||
}
|
||||
|
||||
@Entity(name = "TableA")
|
||||
public static class TableA {
|
||||
|
||||
@Id
|
||||
@Column(name = "table_a_id")
|
||||
private Long tableAId;
|
||||
|
||||
@Column(name = "table_a_character")
|
||||
private String tableACharacter;
|
||||
|
||||
@OneToMany(mappedBy = "tableA")
|
||||
private Set<TableB> tableBs;
|
||||
|
||||
public TableA() {
|
||||
}
|
||||
|
||||
public Long getTableAId() {
|
||||
return this.tableAId;
|
||||
}
|
||||
|
||||
public void setTableAId_(Long _tableAId_) {
|
||||
this.tableAId = _tableAId_;
|
||||
}
|
||||
|
||||
public String getTableACharacter() {
|
||||
return this.tableACharacter;
|
||||
}
|
||||
|
||||
public void setTableACharacter(String _tableACharacter_) {
|
||||
this.tableACharacter = _tableACharacter_;
|
||||
}
|
||||
|
||||
public Set<TableB> getTableBs() {
|
||||
return this.tableBs;
|
||||
}
|
||||
|
||||
public void setTableBs(Set<TableB> tableBs) {
|
||||
this.tableBs = tableBs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "TableB")
|
||||
public static class TableB {
|
||||
|
||||
@Id
|
||||
@Column(name = "table_b_id")
|
||||
private Long tableBId;
|
||||
|
||||
@Column(name = "table_a_id", insertable = false, updatable = false)
|
||||
private Long tableAId;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "table_b_date")
|
||||
private Date tableBDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "table_a_id")
|
||||
private TableA tableA;
|
||||
|
||||
@OneToMany(mappedBy = "tableB")
|
||||
private Set<TableC> tableCs;
|
||||
|
||||
|
||||
public TableB() {
|
||||
}
|
||||
|
||||
public Long getTableBId() {
|
||||
return this.tableBId;
|
||||
}
|
||||
|
||||
public void setTableBId(Long _tableBId_) {
|
||||
this.tableBId = _tableBId_;
|
||||
}
|
||||
|
||||
public Long getTableAId() {
|
||||
return this.tableAId;
|
||||
}
|
||||
|
||||
public void setTableAId(Long _tableAId_) {
|
||||
this.tableAId = _tableAId_;
|
||||
}
|
||||
|
||||
public Date getTableBDate() {
|
||||
return this.tableBDate;
|
||||
}
|
||||
|
||||
public void setTableBDate(Date _tableBDate_) {
|
||||
this.tableBDate = _tableBDate_;
|
||||
}
|
||||
|
||||
public TableA getTableA() {
|
||||
return tableA;
|
||||
}
|
||||
|
||||
public void setTableA(TableA tableA) {
|
||||
this.tableA = tableA;
|
||||
}
|
||||
|
||||
public Set<TableC> getTableCs() {
|
||||
return tableCs;
|
||||
}
|
||||
|
||||
public void setTableCs(Set<TableC> tableCs) {
|
||||
this.tableCs = tableCs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "TableC")
|
||||
public static class TableC {
|
||||
|
||||
@Id
|
||||
@Column(name = "table_c_id")
|
||||
private Long tableCId;
|
||||
|
||||
@Column(name = "table_b_id", insertable = false, updatable = false)
|
||||
private Long tableBId;
|
||||
|
||||
@Column(name = "table_c_boolean")
|
||||
private Boolean tableCBoolean;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "table_b_id")
|
||||
private TableB tableB;
|
||||
|
||||
public TableC() {
|
||||
}
|
||||
|
||||
public Long getTableCId() {
|
||||
return this.tableCId;
|
||||
}
|
||||
|
||||
public void setTableCId(Long tableCId) {
|
||||
this.tableCId = tableCId;
|
||||
}
|
||||
|
||||
public Long getTableBId() {
|
||||
return this.tableBId;
|
||||
}
|
||||
|
||||
public void setTableBId(Long tableBId) {
|
||||
this.tableBId = tableBId;
|
||||
}
|
||||
|
||||
public Boolean getTableCBoolean() {
|
||||
return this.tableCBoolean;
|
||||
}
|
||||
|
||||
public void setTableCBoolean(Boolean tableCBoolean) {
|
||||
this.tableCBoolean = tableCBoolean;
|
||||
}
|
||||
|
||||
public TableB getTableB() {
|
||||
return tableB;
|
||||
}
|
||||
|
||||
public void setTableB(TableB tableB) {
|
||||
this.tableB = tableB;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue