HHH-8312 - named parameters binding are not correct when used within subquery

This commit is contained in:
Strong Liu 2013-06-15 15:58:48 +08:00
parent 6a71cbb991
commit 6cabc326b8
25 changed files with 434 additions and 209 deletions

View File

@ -178,7 +178,7 @@ abstract class AbstractTransactSQLDialect extends Dialect {
} }
@Override @Override
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) { public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
// TODO: merge additional lockoptions support in Dialect.applyLocksToSql // TODO: merge additional lockoptions support in Dialect.applyLocksToSql
final Iterator itr = aliasedLockOptions.getAliasLockIterator(); final Iterator itr = aliasedLockOptions.getAliasLockIterator();
final StringBuilder buffer = new StringBuilder( sql ); final StringBuilder buffer = new StringBuilder( sql );

View File

@ -1452,7 +1452,7 @@ public abstract class Dialect implements ConversionContext {
* @param keyColumnNames a map of key columns indexed by aliased table names. * @param keyColumnNames a map of key columns indexed by aliased table names.
* @return the modified SQL string. * @return the modified SQL string.
*/ */
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) { public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString(); return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
} }

View File

@ -96,7 +96,7 @@ public class SybaseASE157Dialect extends SybaseASE15Dialect {
} }
@Override @Override
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) { public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString(); return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
} }

View File

@ -36,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class ColumnNameCache { public class ColumnNameCache {
private static final float LOAD_FACTOR = .75f; private static final float LOAD_FACTOR = .75f;
private final Map<String, Integer> columnNameToIndexCache; private final ConcurrentHashMap<String, Integer> columnNameToIndexCache;
/** /**
* Constructs a ColumnNameCache * Constructs a ColumnNameCache

View File

@ -69,6 +69,7 @@ import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.IdentitySet; import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.loader.hql.QueryLoader; import org.hibernate.loader.hql.QueryLoader;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -101,7 +102,7 @@ public class QueryTranslatorImpl implements FilterTranslator {
private String sql; private String sql;
private ParameterTranslations paramTranslations; private ParameterTranslations paramTranslations;
private List collectedParameterSpecifications; private List<ParameterSpecification> collectedParameterSpecifications;
/** /**
@ -569,12 +570,11 @@ public class QueryTranslatorImpl implements FilterTranslator {
public ParameterTranslations getParameterTranslations() { public ParameterTranslations getParameterTranslations() {
if ( paramTranslations == null ) { if ( paramTranslations == null ) {
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() ); paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications );
} }
return paramTranslations; return paramTranslations;
} }
public List getCollectedParameterSpecifications() { public List<ParameterSpecification> getCollectedParameterSpecifications() {
return collectedParameterSpecifications; return collectedParameterSpecifications;
} }

View File

@ -76,7 +76,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
private SessionFactoryImplementor sessionFactory; private SessionFactoryImplementor sessionFactory;
private LinkedList<SqlWriter> outputStack = new LinkedList<SqlWriter>(); private LinkedList<SqlWriter> outputStack = new LinkedList<SqlWriter>();
private final ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class ); private final ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
private List collectedParameters = new ArrayList(); private List<ParameterSpecification> collectedParameters = new ArrayList<ParameterSpecification>();
// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -106,7 +106,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
LOG.trace( prefix + ruleName ); LOG.trace( prefix + ruleName );
} }
public List getCollectedParameters() { public List<ParameterSpecification> getCollectedParameters() {
return collectedParameters; return collectedParameters;
} }

View File

@ -452,16 +452,12 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
this.alias = alias; this.alias = alias;
} }
/** @Override
* {@inheritDoc}
*/
public String getSqlFragment() { public String getSqlFragment() {
return persisterDiscriminatorMetadata.getSqlFragment( alias ); return persisterDiscriminatorMetadata.getSqlFragment( alias );
} }
/** @Override
* {@inheritDoc}
*/
public Type getResolutionType() { public Type getResolutionType() {
return persisterDiscriminatorMetadata.getResolutionType(); return persisterDiscriminatorMetadata.getResolutionType();
} }
@ -660,21 +656,24 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
// ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private List embeddedParameters; private List<ParameterSpecification> embeddedParameters;
@Override
public void addEmbeddedParameter(ParameterSpecification specification) { public void addEmbeddedParameter(ParameterSpecification specification) {
if ( embeddedParameters == null ) { if ( embeddedParameters == null ) {
embeddedParameters = new ArrayList(); embeddedParameters = new ArrayList<ParameterSpecification>();
} }
embeddedParameters.add( specification ); embeddedParameters.add( specification );
} }
@Override
public boolean hasEmbeddedParameters() { public boolean hasEmbeddedParameters() {
return embeddedParameters != null && ! embeddedParameters.isEmpty(); return embeddedParameters != null && ! embeddedParameters.isEmpty();
} }
@Override
public ParameterSpecification[] getEmbeddedParameters() { public ParameterSpecification[] getEmbeddedParameters() {
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] ); return embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
} }
public ParameterSpecification getIndexCollectionSelectorParamSpec() { public ParameterSpecification getIndexCollectionSelectorParamSpec() {

View File

@ -147,14 +147,14 @@ public class IndexNode extends FromReferenceNode {
} }
String selectorExpression = gen.getSQL(); String selectorExpression = gen.getSQL();
joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression ); joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression );
List paramSpecs = gen.getCollectedParameters(); List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
if ( paramSpecs != null ) { if ( paramSpecs != null ) {
switch ( paramSpecs.size() ) { switch ( paramSpecs.size() ) {
case 0 : case 0 :
// nothing to do // nothing to do
break; break;
case 1 : case 1 :
ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecs.get( 0 ); ParameterSpecification paramSpec = paramSpecs.get( 0 );
paramSpec.setExpectedType( queryableCollection.getIndexType() ); paramSpec.setExpectedType( queryableCollection.getIndexType() );
fromElement.setIndexCollectionSelectorParamSpec( paramSpec ); fromElement.setIndexCollectionSelectorParamSpec( paramSpec );
break; break;
@ -176,39 +176,40 @@ public class IndexNode extends FromReferenceNode {
* In the (rare?) case where the index selector contains multiple parameters... * In the (rare?) case where the index selector contains multiple parameters...
*/ */
private static class AggregatedIndexCollectionSelectorParameterSpecifications implements ParameterSpecification { private static class AggregatedIndexCollectionSelectorParameterSpecifications implements ParameterSpecification {
private final List paramSpecs; private final List<ParameterSpecification> paramSpecs;
public AggregatedIndexCollectionSelectorParameterSpecifications(List paramSpecs) { public AggregatedIndexCollectionSelectorParameterSpecifications(List<ParameterSpecification> paramSpecs) {
this.paramSpecs = paramSpecs; this.paramSpecs = paramSpecs;
} }
@Override
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position) public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
throws SQLException { throws SQLException {
int bindCount = 0; int bindCount = 0;
Iterator itr = paramSpecs.iterator(); for ( ParameterSpecification paramSpec : paramSpecs ) {
while ( itr.hasNext() ) {
final ParameterSpecification paramSpec = ( ParameterSpecification ) itr.next();
bindCount += paramSpec.bind( statement, qp, session, position + bindCount ); bindCount += paramSpec.bind( statement, qp, session, position + bindCount );
} }
return bindCount; return bindCount;
} }
@Override
public Type getExpectedType() { public Type getExpectedType() {
return null; return null;
} }
@Override
public void setExpectedType(Type expectedType) { public void setExpectedType(Type expectedType) {
} }
@Override
public String renderDisplayInfo() { public String renderDisplayInfo() {
return "index-selector [" + collectDisplayInfo() + "]" ; return "index-selector [" + collectDisplayInfo() + "]" ;
} }
private String collectDisplayInfo() { private String collectDisplayInfo() {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
Iterator itr = paramSpecs.iterator(); for ( ParameterSpecification paramSpec : paramSpecs ) {
while ( itr.hasNext() ) { buffer.append( ( paramSpec ).renderDisplayInfo() );
buffer.append( ( ( ParameterSpecification ) itr.next() ).renderDisplayInfo() );
} }
return buffer.toString(); return buffer.toString();
} }

View File

@ -79,6 +79,7 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.FetchingScrollableResultsImpl; import org.hibernate.internal.FetchingScrollableResultsImpl;
import org.hibernate.internal.ScrollableResultsImpl; import org.hibernate.internal.ScrollableResultsImpl;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.loader.spi.AfterLoadAction; import org.hibernate.loader.spi.AfterLoadAction;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -110,7 +111,7 @@ import org.hibernate.type.VersionType;
public abstract class Loader { public abstract class Loader {
protected static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Loader.class.getName()); protected static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Loader.class.getName());
protected static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
private final SessionFactoryImplementor factory; private final SessionFactoryImplementor factory;
private ColumnNameCache columnNameCache; private ColumnNameCache columnNameCache;
@ -931,9 +932,9 @@ public abstract class Loader {
EntityKey[] keys = new EntityKey[entitySpan]; //we can reuse it for each row EntityKey[] keys = new EntityKey[entitySpan]; //we can reuse it for each row
LOG.trace( "Processing result set" ); LOG.trace( "Processing result set" );
int count; int count;
boolean isDebugEnabled = LOG.isDebugEnabled();
for ( count = 0; count < maxRows && rs.next(); count++ ) { for ( count = 0; count < maxRows && rs.next(); count++ ) {
if ( isDebugEnabled ) if ( DEBUG_ENABLED )
LOG.debugf( "Result set row: %s", count ); LOG.debugf( "Result set row: %s", count );
Object result = getRowFromResultSet( Object result = getRowFromResultSet(
rs, rs,
@ -975,8 +976,10 @@ public abstract class Loader {
protected boolean hasSubselectLoadableCollections() { protected boolean hasSubselectLoadableCollections() {
final Loadable[] loadables = getEntityPersisters(); final Loadable[] loadables = getEntityPersisters();
for (int i=0; i<loadables.length; i++ ) { for ( Loadable loadable : loadables ) {
if ( loadables[i].hasSubselectLoadableCollections() ) return true; if ( loadable.hasSubselectLoadableCollections() ) {
return true;
}
} }
return false; return false;
} }
@ -985,8 +988,8 @@ public abstract class Loader {
Set[] result = new Set[ ( ( EntityKey[] ) keys.get(0) ).length ]; Set[] result = new Set[ ( ( EntityKey[] ) keys.get(0) ).length ];
for ( int j=0; j<result.length; j++ ) { for ( int j=0; j<result.length; j++ ) {
result[j] = new HashSet( keys.size() ); result[j] = new HashSet( keys.size() );
for ( int i=0; i<keys.size(); i++ ) { for ( Object key : keys ) {
result[j].add( ( ( EntityKey[] ) keys.get(i) ) [j] ); result[j].add( ( (EntityKey[]) key )[j] );
} }
} }
return result; return result;
@ -1032,13 +1035,11 @@ public abstract class Loader {
private Map buildNamedParameterLocMap(QueryParameters queryParameters) { private Map buildNamedParameterLocMap(QueryParameters queryParameters) {
if ( queryParameters.getNamedParameters()!=null ) { if ( queryParameters.getNamedParameters()!=null ) {
final Map namedParameterLocMap = new HashMap(); final Map namedParameterLocMap = new HashMap();
Iterator piter = queryParameters.getNamedParameters().keySet().iterator(); for(String name : queryParameters.getNamedParameters().keySet()){
while ( piter.hasNext() ) {
String name = (String) piter.next();
namedParameterLocMap.put( namedParameterLocMap.put(
name, name,
getNamedParameterLocs(name) getNamedParameterLocs(name)
); );
} }
return namedParameterLocMap; return namedParameterLocMap;
} }
@ -1992,30 +1993,33 @@ public abstract class Loader {
*/ */
protected int bindNamedParameters( protected int bindNamedParameters(
final PreparedStatement statement, final PreparedStatement statement,
final Map namedParams, final Map<String, TypedValue> namedParams,
final int startIndex, final int startIndex,
final SessionImplementor session) throws SQLException, HibernateException { final SessionImplementor session) throws SQLException, HibernateException {
if ( namedParams != null ) { int result = 0;
// assumes that types are all of span 1 if ( CollectionHelper.isEmpty( namedParams ) ) {
Iterator iter = namedParams.entrySet().iterator();
final boolean debugEnabled = LOG.isDebugEnabled();
int result = 0;
while ( iter.hasNext() ) {
Map.Entry e = ( Map.Entry ) iter.next();
String name = ( String ) e.getKey();
TypedValue typedval = ( TypedValue ) e.getValue();
int[] locs = getNamedParameterLocs( name );
for ( int i = 0; i < locs.length; i++ ) {
if ( debugEnabled ) LOG.debugf( "bindNamedParameters() %s -> %s [%s]", typedval.getValue(), name, locs[i] + startIndex );
typedval.getType().nullSafeSet( statement, typedval.getValue(), locs[i] + startIndex, session );
}
result += locs.length;
}
return result; return result;
} }
else {
return 0; for ( String name : namedParams.keySet() ) {
TypedValue typedValue = namedParams.get( name );
int columnSpan = typedValue.getType().getColumnSpan( getFactory() );
int[] locs = getNamedParameterLocs( name );
for ( int loc : locs ) {
if ( DEBUG_ENABLED ) {
LOG.debugf(
"bindNamedParameters() %s -> %s [%s]",
typedValue.getValue(),
name,
loc + startIndex
);
}
int start = loc * columnSpan + startIndex;
typedValue.getType().nullSafeSet( statement, typedValue.getValue(), start, session );
}
result += locs.length;
} }
return result;
} }
public int[] getNamedParameterLocs(String name) { public int[] getNamedParameterLocs(String name) {
@ -2080,7 +2084,7 @@ public abstract class Loader {
private ColumnNameCache retreiveColumnNameToIndexCache(ResultSet rs) throws SQLException { private ColumnNameCache retreiveColumnNameToIndexCache(ResultSet rs) throws SQLException {
if ( columnNameCache == null ) { if ( columnNameCache == null ) {
LOG.trace( "Building columnName->columnIndex cache" ); LOG.trace( "Building columnName -> columnIndex cache" );
columnNameCache = new ColumnNameCache( rs.getMetaData().getColumnCount() ); columnNameCache = new ColumnNameCache( rs.getMetaData().getColumnCount() );
} }
@ -2293,7 +2297,7 @@ public abstract class Loader {
final Serializable[] ids, final Serializable[] ids,
final Object[] parameterValues, final Object[] parameterValues,
final Type[] parameterTypes, final Type[] parameterTypes,
final Map namedParameters, final Map<String, TypedValue> namedParameters,
final Type type) throws HibernateException { final Type type) throws HibernateException {
Type[] idTypes = new Type[ids.length]; Type[] idTypes = new Type[ids.length];
@ -2551,7 +2555,6 @@ public abstract class Loader {
// whether scrolling of their result set should be allowed. // whether scrolling of their result set should be allowed.
// //
// By default it is allowed. // By default it is allowed.
return;
} }
/** /**

View File

@ -35,6 +35,7 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -47,15 +48,15 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
private final Serializable[] keys; private final Serializable[] keys;
private final Type[] types; private final Type[] types;
private final Object[] values; private final Object[] values;
private final Map namedParameters; private final Map<String, TypedValue> namedParameters;
private final Map namedParameterLocMap; private final Map<String, int[]> namedParameterLocMap;
public SubselectCollectionLoader( public SubselectCollectionLoader(
QueryableCollection persister, QueryableCollection persister,
String subquery, String subquery,
Collection entityKeys, Collection entityKeys,
QueryParameters queryParameters, QueryParameters queryParameters,
Map namedParameterLocMap, Map<String, int[]> namedParameterLocMap,
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) throws MappingException { LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
super( persister, 1, subquery, factory, loadQueryInfluencers ); super( persister, 1, subquery, factory, loadQueryInfluencers );
@ -74,6 +75,7 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
} }
@Override
public void initialize(Serializable id, SessionImplementor session) public void initialize(Serializable id, SessionImplementor session)
throws HibernateException { throws HibernateException {
loadCollectionSubselect( loadCollectionSubselect(
@ -86,8 +88,9 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
); );
} }
@Override
public int[] getNamedParameterLocs(String name) { public int[] getNamedParameterLocs(String name) {
return (int[]) namedParameterLocMap.get( name ); return namedParameterLocMap.get( name );
} }
} }

View File

@ -35,6 +35,7 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -47,15 +48,15 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
private final Serializable[] keys; private final Serializable[] keys;
private final Type[] types; private final Type[] types;
private final Object[] values; private final Object[] values;
private final Map namedParameters; private final Map<String, TypedValue> namedParameters;
private final Map namedParameterLocMap; private final Map<String, int[]> namedParameterLocMap;
public SubselectOneToManyLoader( public SubselectOneToManyLoader(
QueryableCollection persister, QueryableCollection persister,
String subquery, String subquery,
Collection entityKeys, Collection entityKeys,
QueryParameters queryParameters, QueryParameters queryParameters,
Map namedParameterLocMap, Map<String, int[]> namedParameterLocMap,
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) throws MappingException { LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
super( persister, 1, subquery, factory, loadQueryInfluencers ); super( persister, 1, subquery, factory, loadQueryInfluencers );
@ -73,6 +74,7 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
this.namedParameterLocMap = namedParameterLocMap; this.namedParameterLocMap = namedParameterLocMap;
} }
@Override
public void initialize(Serializable id, SessionImplementor session) throws HibernateException { public void initialize(Serializable id, SessionImplementor session) throws HibernateException {
loadCollectionSubselect( loadCollectionSubselect(
session, session,
@ -83,9 +85,9 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
getKeyType() getKeyType()
); );
} }
@Override
public int[] getNamedParameterLocs(String name) { public int[] getNamedParameterLocs(String name) {
return (int[]) namedParameterLocMap.get( name ); return namedParameterLocMap.get( name );
} }
} }

View File

@ -459,7 +459,7 @@ public class CustomLoader extends Loader {
); );
} }
if ( loc instanceof Integer ) { if ( loc instanceof Integer ) {
return new int[] { ( ( Integer ) loc ).intValue() }; return new int[] { (Integer) loc };
} }
else { else {
return ArrayHelper.toIntArray( ( List ) loc ); return ArrayHelper.toIntArray( ( List ) loc );

View File

@ -88,7 +88,7 @@ public class QueryLoader extends BasicLoader {
//private Type[] sqlResultTypes; //private Type[] sqlResultTypes;
private Type[] queryReturnTypes; private Type[] queryReturnTypes;
private final Map sqlAliasByEntityAlias = new HashMap(8); private final Map<String, String> sqlAliasByEntityAlias = new HashMap<String, String>(8);
private EntityType[] ownerAssociationTypes; private EntityType[] ownerAssociationTypes;
private int[] owners; private int[] owners;
@ -209,15 +209,15 @@ public class QueryLoader extends BasicLoader {
public final void validateScrollability() throws HibernateException { public final void validateScrollability() throws HibernateException {
queryTranslator.validateScrollability(); queryTranslator.validateScrollability();
} }
@Override
protected boolean needsFetchingScroll() { protected boolean needsFetchingScroll() {
return queryTranslator.containsCollectionFetches(); return queryTranslator.containsCollectionFetches();
} }
@Override
public Loadable[] getEntityPersisters() { public Loadable[] getEntityPersisters() {
return entityPersisters; return entityPersisters;
} }
@Override
public String[] getAliases() { public String[] getAliases() {
return sqlAliases; return sqlAliases;
} }
@ -225,15 +225,15 @@ public class QueryLoader extends BasicLoader {
public String[] getSqlAliasSuffixes() { public String[] getSqlAliasSuffixes() {
return sqlAliasSuffixes; return sqlAliasSuffixes;
} }
@Override
public String[] getSuffixes() { public String[] getSuffixes() {
return getSqlAliasSuffixes(); return getSqlAliasSuffixes();
} }
@Override
public String[] getCollectionSuffixes() { public String[] getCollectionSuffixes() {
return collectionSuffixes; return collectionSuffixes;
} }
@Override
protected String getQueryIdentifier() { protected String getQueryIdentifier() {
return queryTranslator.getQueryIdentifier(); return queryTranslator.getQueryIdentifier();
} }
@ -241,6 +241,7 @@ public class QueryLoader extends BasicLoader {
/** /**
* The SQL query string to be called. * The SQL query string to be called.
*/ */
@Override
public String getSQLString() { public String getSQLString() {
return queryTranslator.getSQLString(); return queryTranslator.getSQLString();
} }
@ -249,14 +250,15 @@ public class QueryLoader extends BasicLoader {
* An (optional) persister for a collection to be initialized; only collection loaders * An (optional) persister for a collection to be initialized; only collection loaders
* return a non-null value * return a non-null value
*/ */
@Override
protected CollectionPersister[] getCollectionPersisters() { protected CollectionPersister[] getCollectionPersisters() {
return collectionPersisters; return collectionPersisters;
} }
@Override
protected int[] getCollectionOwners() { protected int[] getCollectionOwners() {
return collectionOwners; return collectionOwners;
} }
@Override
protected boolean[] getEntityEagerPropertyFetches() { protected boolean[] getEntityEagerPropertyFetches() {
return entityEagerPropertyFetches; return entityEagerPropertyFetches;
} }
@ -265,16 +267,17 @@ public class QueryLoader extends BasicLoader {
* An array of indexes of the entity that owns a one-to-one association * An array of indexes of the entity that owns a one-to-one association
* to the entity at the given index (-1 if there is no "owner") * to the entity at the given index (-1 if there is no "owner")
*/ */
@Override
protected int[] getOwners() { protected int[] getOwners() {
return owners; return owners;
} }
@Override
protected EntityType[] getOwnerAssociationTypes() { protected EntityType[] getOwnerAssociationTypes() {
return ownerAssociationTypes; return ownerAssociationTypes;
} }
// -- Loader overrides -- // -- Loader overrides --
@Override
protected boolean isSubselectLoadingEnabled() { protected boolean isSubselectLoadingEnabled() {
return hasSubselectLoadableCollections(); return hasSubselectLoadableCollections();
} }
@ -282,6 +285,7 @@ public class QueryLoader extends BasicLoader {
/** /**
* @param lockOptions a collection of lock modes specified dynamically via the Query interface * @param lockOptions a collection of lock modes specified dynamically via the Query interface
*/ */
@Override
protected LockMode[] getLockModes(LockOptions lockOptions) { protected LockMode[] getLockModes(LockOptions lockOptions) {
if ( lockOptions == null ) { if ( lockOptions == null ) {
return defaultLockModes; return defaultLockModes;
@ -341,16 +345,14 @@ public class QueryLoader extends BasicLoader {
// we need both the set of locks and the columns to reference in locks // we need both the set of locks and the columns to reference in locks
// as the ultimate output of this section... // as the ultimate output of this section...
final LockOptions locks = new LockOptions( lockOptions.getLockMode() ); final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
final Map keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null; final Map<String, String[]> keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap<String, String[]>() : null;
locks.setScope( lockOptions.getScope() ); locks.setScope( lockOptions.getScope() );
locks.setTimeOut( lockOptions.getTimeOut() ); locks.setTimeOut( lockOptions.getTimeOut() );
final Iterator itr = sqlAliasByEntityAlias.entrySet().iterator(); for ( Map.Entry<String, String> entry : sqlAliasByEntityAlias.entrySet() ) {
while ( itr.hasNext() ) { final String userAlias = entry.getKey();
final Map.Entry entry = (Map.Entry) itr.next(); final String drivingSqlAlias = entry.getValue();
final String userAlias = (String) entry.getKey();
final String drivingSqlAlias = (String) entry.getValue();
if ( drivingSqlAlias == null ) { if ( drivingSqlAlias == null ) {
throw new IllegalArgumentException( "could not locate alias to apply lock mode : " + userAlias ); throw new IllegalArgumentException( "could not locate alias to apply lock mode : " + userAlias );
} }
@ -360,8 +362,8 @@ public class QueryLoader extends BasicLoader {
// the exception case here is joined-subclass hierarchies where we instead // the exception case here is joined-subclass hierarchies where we instead
// want to apply the lock against the root table (for all other strategies, // want to apply the lock against the root table (for all other strategies,
// it just happens that driving and root are the same). // it just happens that driving and root are the same).
final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST(); final QueryNode select = (QueryNode) queryTranslator.getSqlAST();
final Lockable drivingPersister = ( Lockable ) select.getFromClause() final Lockable drivingPersister = (Lockable) select.getFromClause()
.findFromElementByUserOrSqlAlias( userAlias, drivingSqlAlias ) .findFromElementByUserOrSqlAlias( userAlias, drivingSqlAlias )
.getQueryable(); .getQueryable();
final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias ); final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
@ -377,7 +379,7 @@ public class QueryLoader extends BasicLoader {
// apply the collected locks and columns // apply the collected locks and columns
return dialect.applyLocksToSql( sql, locks, keyColumnNames ); return dialect.applyLocksToSql( sql, locks, keyColumnNames );
} }
@Override
protected void applyPostLoadLocks(Object[] row, LockMode[] lockModesArray, SessionImplementor session) { protected void applyPostLoadLocks(Object[] row, LockMode[] lockModesArray, SessionImplementor session) {
// todo : scalars??? // todo : scalars???
// if ( row.length != lockModesArray.length ) { // if ( row.length != lockModesArray.length ) {
@ -393,7 +395,7 @@ public class QueryLoader extends BasicLoader {
// } // }
// } // }
} }
@Override
protected boolean upgradeLocks() { protected boolean upgradeLocks() {
return true; return true;
} }
@ -401,18 +403,18 @@ public class QueryLoader extends BasicLoader {
private boolean hasSelectNew() { private boolean hasSelectNew() {
return aggregatedSelectExpression != null && aggregatedSelectExpression.getResultTransformer() != null; return aggregatedSelectExpression != null && aggregatedSelectExpression.getResultTransformer() != null;
} }
@Override
protected String[] getResultRowAliases() { protected String[] getResultRowAliases() {
return queryReturnAliases; return queryReturnAliases;
} }
@Override
protected ResultTransformer resolveResultTransformer(ResultTransformer resultTransformer) { protected ResultTransformer resolveResultTransformer(ResultTransformer resultTransformer) {
final ResultTransformer implicitResultTransformer = aggregatedSelectExpression == null final ResultTransformer implicitResultTransformer = aggregatedSelectExpression == null
? null ? null
: aggregatedSelectExpression.getResultTransformer(); : aggregatedSelectExpression.getResultTransformer();
return HolderInstantiator.resolveResultTransformer( implicitResultTransformer, resultTransformer ); return HolderInstantiator.resolveResultTransformer( implicitResultTransformer, resultTransformer );
} }
@Override
protected boolean[] includeInResultRow() { protected boolean[] includeInResultRow() {
boolean[] includeInResultTuple = includeInSelect; boolean[] includeInResultTuple = includeInSelect;
if ( hasScalars ) { if ( hasScalars ) {
@ -421,7 +423,7 @@ public class QueryLoader extends BasicLoader {
} }
return includeInResultTuple; return includeInResultTuple;
} }
@Override
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 { throws SQLException, HibernateException {
@ -433,6 +435,7 @@ public class QueryLoader extends BasicLoader {
); );
} }
@Override
protected Object[] getResultRow(Object[] row, ResultSet rs, SessionImplementor session) protected Object[] getResultRow(Object[] row, ResultSet rs, SessionImplementor session)
throws SQLException, HibernateException { throws SQLException, HibernateException {
Object[] resultRow; Object[] resultRow;
@ -450,6 +453,8 @@ public class QueryLoader extends BasicLoader {
return resultRow; return resultRow;
} }
@SuppressWarnings("unchecked")
@Override
protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException { protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException {
// meant to handle dynamic instantiation queries... // meant to handle dynamic instantiation queries...
HolderInstantiator holderInstantiator = buildHolderInstantiator( resultTransformer ); HolderInstantiator holderInstantiator = buildHolderInstantiator( resultTransformer );
@ -579,6 +584,7 @@ public class QueryLoader extends BasicLoader {
/** /**
* Returns the locations of all occurrences of the named parameter. * Returns the locations of all occurrences of the named parameter.
*/ */
@Override
public int[] getNamedParameterLocs(String name) throws QueryException { public int[] getNamedParameterLocs(String name) throws QueryException {
return queryTranslator.getParameterTranslations().getNamedParameterSqlLocations( name ); return queryTranslator.getParameterTranslations().getNamedParameterSqlLocations( name );
} }
@ -586,7 +592,7 @@ public class QueryLoader extends BasicLoader {
/** /**
* We specifically override this method here, because in general we know much more * We specifically override this method here, because in general we know much more
* about the parameters and their appropriate bind positions here then we do in * about the parameters and their appropriate bind positions here then we do in
* our super because we track them explciitly here through the ParameterSpecification * our super because we track them explicitly here through the ParameterSpecification
* interface. * interface.
* *
* @param queryParameters The encapsulation of the parameter values to be bound. * @param queryParameters The encapsulation of the parameter values to be bound.
@ -595,45 +601,17 @@ public class QueryLoader extends BasicLoader {
* @return The number of JDBC bind positions actually bound during this method execution. * @return The number of JDBC bind positions actually bound during this method execution.
* @throws SQLException Indicates problems performing the binding. * @throws SQLException Indicates problems performing the binding.
*/ */
@Override
protected int bindParameterValues( protected int bindParameterValues(
final PreparedStatement statement, final PreparedStatement statement,
final QueryParameters queryParameters, final QueryParameters queryParameters,
final int startIndex, final int startIndex,
final SessionImplementor session) throws SQLException { final SessionImplementor session) throws SQLException {
// int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
int position = startIndex; int position = startIndex;
// List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters(); List<ParameterSpecification> parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
List parameterSpecs = queryTranslator.getCollectedParameterSpecifications(); for ( ParameterSpecification spec : parameterSpecs ) {
Iterator itr = parameterSpecs.iterator();
while ( itr.hasNext() ) {
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
position += spec.bind( statement, queryParameters, session, position ); position += spec.bind( statement, queryParameters, session, position );
} }
return position - startIndex; return position - startIndex;
} }
private int bindFilterParameterValues(
PreparedStatement st,
QueryParameters queryParameters,
int position,
SessionImplementor session) throws SQLException {
// todo : better to handle dynamic filters through implicit DynamicFilterParameterSpecification
// see the discussion there in DynamicFilterParameterSpecification's javadocs as to why
// it is currently not done that way.
int filteredParamCount = queryParameters.getFilteredPositionalParameterTypes() == null
? 0
: queryParameters.getFilteredPositionalParameterTypes().length;
int nonfilteredParamCount = queryParameters.getPositionalParameterTypes() == null
? 0
: queryParameters.getPositionalParameterTypes().length;
int filterParamCount = filteredParamCount - nonfilteredParamCount;
for ( int i = 0; i < filterParamCount; i++ ) {
Type type = queryParameters.getFilteredPositionalParameterTypes()[i];
Object value = queryParameters.getFilteredPositionalParameterValues()[i];
type.nullSafeSet( st, value, position, session );
position += type.getColumnSpan( getFactory() );
}
return position;
}
} }

View File

@ -46,30 +46,22 @@ public abstract class AbstractExplicitParameterSpecification implements Explicit
this.sourceColumn = sourceColumn; this.sourceColumn = sourceColumn;
} }
/** @Override
* {@inheritDoc}
*/
public int getSourceLine() { public int getSourceLine() {
return sourceLine; return sourceLine;
} }
/** @Override
* {@inheritDoc}
*/
public int getSourceColumn() { public int getSourceColumn() {
return sourceColumn; return sourceColumn;
} }
/** @Override
* {@inheritDoc}
*/
public Type getExpectedType() { public Type getExpectedType() {
return expectedType; return expectedType;
} }
/** @Override
* {@inheritDoc}
*/
public void setExpectedType(Type expectedType) { public void setExpectedType(Type expectedType) {
this.expectedType = expectedType; this.expectedType = expectedType;
} }

View File

@ -55,9 +55,7 @@ public class CollectionFilterKeyParameterSpecification implements ParameterSpeci
this.queryParameterPosition = queryParameterPosition; this.queryParameterPosition = queryParameterPosition;
} }
/** @Override
* {@inheritDoc}
*/
public int bind( public int bind(
PreparedStatement statement, PreparedStatement statement,
QueryParameters qp, QueryParameters qp,
@ -68,23 +66,17 @@ public class CollectionFilterKeyParameterSpecification implements ParameterSpeci
return keyType.getColumnSpan( session.getFactory() ); return keyType.getColumnSpan( session.getFactory() );
} }
/** @Override
* {@inheritDoc}
*/
public Type getExpectedType() { public Type getExpectedType() {
return keyType; return keyType;
} }
/** @Override
* {@inheritDoc}
*/
public void setExpectedType(Type expectedType) { public void setExpectedType(Type expectedType) {
// todo : throw exception? // todo : throw exception?
} }
/** @Override
* {@inheritDoc}
*/
public String renderDisplayInfo() { public String renderDisplayInfo() {
return "collection-filter-key=" + collectionRole; return "collection-filter-key=" + collectionRole;
} }

View File

@ -60,9 +60,7 @@ public class DynamicFilterParameterSpecification implements ParameterSpecificati
this.definedParameterType = definedParameterType; this.definedParameterType = definedParameterType;
} }
/** @Override
* {@inheritDoc}
*/
public int bind( public int bind(
PreparedStatement statement, PreparedStatement statement,
QueryParameters qp, QueryParameters qp,
@ -85,23 +83,17 @@ public class DynamicFilterParameterSpecification implements ParameterSpecificati
} }
} }
/** @Override
* {@inheritDoc}
*/
public Type getExpectedType() { public Type getExpectedType() {
return definedParameterType; return definedParameterType;
} }
/** @Override
* {@inheritDoc}
*/
public void setExpectedType(Type expectedType) { public void setExpectedType(Type expectedType) {
// todo : throw exception? maybe warn if not the same? // todo : throw exception? maybe warn if not the same?
} }
/** @Override
* {@inheritDoc}
*/
public String renderDisplayInfo() { public String renderDisplayInfo() {
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}"; return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
} }

View File

@ -35,7 +35,7 @@ import org.hibernate.engine.spi.TypedValue;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification { public class NamedParameterSpecification extends AbstractExplicitParameterSpecification {
private final String name; private final String name;
/** /**

View File

@ -35,7 +35,7 @@ import org.hibernate.type.Type;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification { public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification {
private final int hqlPosition; private final int hqlPosition;
/** /**

View File

@ -37,7 +37,7 @@ import org.hibernate.type.VersionType;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class VersionTypeSeedParameterSpecification implements ParameterSpecification { public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
private VersionType type; private final VersionType type;
/** /**
* Constructs a version seed parameter bind specification. * Constructs a version seed parameter bind specification.
@ -48,32 +48,24 @@ public class VersionTypeSeedParameterSpecification implements ParameterSpecifica
this.type = type; this.type = type;
} }
/** @Override
* {@inheritDoc}
*/
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position) public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
throws SQLException { throws SQLException {
type.nullSafeSet( statement, type.seed( session ), position, session ); type.nullSafeSet( statement, type.seed( session ), position, session );
return 1; return 1;
} }
/** @Override
* {@inheritDoc}
*/
public Type getExpectedType() { public Type getExpectedType() {
return type; return type;
} }
/** @Override
* {@inheritDoc}
*/
public void setExpectedType(Type expectedType) { public void setExpectedType(Type expectedType) {
// expected type is intrinsic here... // expected type is intrinsic here...
} }
/** @Override
* {@inheritDoc}
*/
public String renderDisplayInfo() { public String renderDisplayInfo() {
return "version-seed, type=" + type; return "version-seed, type=" + type;
} }

View File

@ -48,7 +48,7 @@ public class ForUpdateFragment {
this.dialect = dialect; this.dialect = dialect;
} }
public ForUpdateFragment(Dialect dialect, LockOptions lockOptions, Map keyColumnNames) throws QueryException { public ForUpdateFragment(Dialect dialect, LockOptions lockOptions, Map<String, String[]> keyColumnNames) throws QueryException {
this( dialect ); this( dialect );
LockMode upgradeType = null; LockMode upgradeType = null;
Iterator iter = lockOptions.getAliasLockIterator(); Iterator iter = lockOptions.getAliasLockIterator();
@ -68,13 +68,13 @@ public class ForUpdateFragment {
if ( LockMode.READ.lessThan( lockMode ) ) { if ( LockMode.READ.lessThan( lockMode ) ) {
final String tableAlias = ( String ) me.getKey(); final String tableAlias = ( String ) me.getKey();
if ( dialect.forUpdateOfColumns() ) { if ( dialect.forUpdateOfColumns() ) {
String[] keyColumns = ( String[] ) keyColumnNames.get( tableAlias ); //use the id column alias String[] keyColumns = keyColumnNames.get( tableAlias ); //use the id column alias
if ( keyColumns == null ) { if ( keyColumns == null ) {
throw new IllegalArgumentException( "alias not found: " + tableAlias ); throw new IllegalArgumentException( "alias not found: " + tableAlias );
} }
keyColumns = StringHelper.qualify( tableAlias, keyColumns ); keyColumns = StringHelper.qualify( tableAlias, keyColumns );
for ( int i = 0; i < keyColumns.length; i++ ) { for ( String keyColumn : keyColumns ) {
addTableAlias( keyColumns[i] ); addTableAlias( keyColumn );
} }
} }
else { else {

View File

@ -120,8 +120,8 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
int n = 0; int n = 0;
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
int[] subtypes = propertyTypes[i].sqlTypes( mapping ); int[] subtypes = propertyTypes[i].sqlTypes( mapping );
for ( int j = 0; j < subtypes.length; j++ ) { for ( int subtype : subtypes ) {
sqlTypes[n++] = subtypes[j]; sqlTypes[n++] = subtype;
} }
} }
return sqlTypes; return sqlTypes;
@ -327,7 +327,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return old != null; return old != null;
} }
if ( old == null ) { if ( old == null ) {
return current != null; return true;
} }
Object[] currentValues = getPropertyValues( current, session ); Object[] currentValues = getPropertyValues( current, session );
Object[] oldValues = ( Object[] ) old; Object[] oldValues = ( Object[] ) old;
@ -344,12 +344,12 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return false; return false;
} }
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
return resolve( hydrate( rs, names, session, owner ), session, owner ); return resolve( hydrate( rs, names, session, owner ), session, owner );
} }
@Override
public void nullSafeSet(PreparedStatement st, Object value, int begin, SessionImplementor session) public void nullSafeSet(PreparedStatement st, Object value, int begin, SessionImplementor session)
throws HibernateException, SQLException { throws HibernateException, SQLException {
@ -360,7 +360,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
begin += propertyTypes[i].getColumnSpan( session.getFactory() ); begin += propertyTypes[i].getColumnSpan( session.getFactory() );
} }
} }
@Override
public void nullSafeSet( public void nullSafeSet(
PreparedStatement st, PreparedStatement st,
Object value, Object value,
@ -401,13 +401,13 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return getPropertyValues( value, entityMode ); return getPropertyValues( value, entityMode );
} }
} }
@Override
public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner) public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
return nullSafeGet( rs, new String[] {name}, session, owner ); return nullSafeGet( rs, new String[] {name}, session, owner );
} }
@Override
public Object getPropertyValue(Object component, int i, SessionImplementor session) public Object getPropertyValue(Object component, int i, SessionImplementor session)
throws HibernateException { throws HibernateException {
return getPropertyValue( component, i, entityMode ); return getPropertyValue( component, i, entityMode );
@ -417,12 +417,12 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
throws HibernateException { throws HibernateException {
return componentTuplizer.getPropertyValue( component, i ); return componentTuplizer.getPropertyValue( component, i );
} }
@Override
public Object[] getPropertyValues(Object component, SessionImplementor session) public Object[] getPropertyValues(Object component, SessionImplementor session)
throws HibernateException { throws HibernateException {
return getPropertyValues( component, entityMode ); return getPropertyValues( component, entityMode );
} }
@Override
public Object[] getPropertyValues(Object component, EntityMode entityMode) public Object[] getPropertyValues(Object component, EntityMode entityMode)
throws HibernateException { throws HibernateException {
if ( component instanceof Object[] ) { if ( component instanceof Object[] ) {
@ -435,40 +435,41 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return componentTuplizer.getPropertyValues( component ); return componentTuplizer.getPropertyValues( component );
} }
} }
@Override
public void setPropertyValues(Object component, Object[] values, EntityMode entityMode) public void setPropertyValues(Object component, Object[] values, EntityMode entityMode)
throws HibernateException { throws HibernateException {
componentTuplizer.setPropertyValues( component, values ); componentTuplizer.setPropertyValues( component, values );
} }
@Override
public Type[] getSubtypes() { public Type[] getSubtypes() {
return propertyTypes; return propertyTypes;
} }
@Override
public String getName() { public String getName() {
return "component" + ArrayHelper.toString( propertyNames ); return "component" + ArrayHelper.toString( propertyNames );
} }
@Override
public String toLoggableString(Object value, SessionFactoryImplementor factory) public String toLoggableString(Object value, SessionFactoryImplementor factory)
throws HibernateException { throws HibernateException {
if ( value == null ) { if ( value == null ) {
return "null"; return "null";
} }
Map result = new HashMap();
if ( entityMode == null ) { if ( entityMode == null ) {
throw new ClassCastException( value.getClass().getName() ); throw new ClassCastException( value.getClass().getName() );
} }
Map<String,String> result = new HashMap<String, String>();
Object[] values = getPropertyValues( value, entityMode ); Object[] values = getPropertyValues( value, entityMode );
for ( int i = 0; i < propertyTypes.length; i++ ) { for ( int i = 0; i < propertyTypes.length; i++ ) {
result.put( propertyNames[i], propertyTypes[i].toLoggableString( values[i], factory ) ); result.put( propertyNames[i], propertyTypes[i].toLoggableString( values[i], factory ) );
} }
return StringHelper.unqualify( getName() ) + result.toString(); return StringHelper.unqualify( getName() ) + result.toString();
} }
@Override
public String[] getPropertyNames() { public String[] getPropertyNames() {
return propertyNames; return propertyNames;
} }
@Override
public Object deepCopy(Object component, SessionFactoryImplementor factory) public Object deepCopy(Object component, SessionFactoryImplementor factory)
throws HibernateException { throws HibernateException {
if ( component == null ) { if ( component == null ) {
@ -491,7 +492,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return result; return result;
} }
@Override
public Object replace( public Object replace(
Object original, Object original,
Object target, Object target,
@ -577,11 +578,11 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return result; return result;
} }
@Override
public CascadeStyle getCascadeStyle(int i) { public CascadeStyle getCascadeStyle(int i) {
return cascade[i]; return cascade[i];
} }
@Override
public boolean isMutable() { public boolean isMutable() {
return true; return true;
} }
@ -620,7 +621,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return result; return result;
} }
} }
@Override
public FetchMode getFetchMode(int i) { public FetchMode getFetchMode(int i) {
return joinedFetch[i]; return joinedFetch[i];
} }
@ -681,7 +682,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
//for components with many-to-one associations //for components with many-to-one associations
return resolve( value, session, owner ); return resolve( value, session, owner );
} }
@Override
public boolean[] getPropertyNullability() { public boolean[] getPropertyNullability() {
return propertyNullability; return propertyNullability;
} }
@ -690,15 +691,15 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
public boolean isXMLElement() { public boolean isXMLElement() {
return true; return true;
} }
@Override
public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException { public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
return xml; return xml;
} }
@Override
public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException { public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException {
replaceNode( node, ( Element ) value ); replaceNode( node, ( Element ) value );
} }
@Override
public boolean[] toColumnNullness(Object value, Mapping mapping) { public boolean[] toColumnNullness(Object value, Mapping mapping) {
boolean[] result = new boolean[ getColumnSpan( mapping ) ]; boolean[] result = new boolean[ getColumnSpan( mapping ) ];
if ( value == null ) { if ( value == null ) {
@ -713,7 +714,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
} }
return result; return result;
} }
@Override
public boolean isEmbedded() { public boolean isEmbedded() {
return false; return false;
} }

View File

@ -0,0 +1,89 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. 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 Inc.
*
* 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.subselect;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* @author Strong Liu <stliu@hibernate.org>
*/
@SkipForDialect(value = H2Dialect.class, comment = "H2 doesn't support this sql syntax")
@TestForIssue( jiraKey = "HHH-8312")
public class CompositeIdTypeBindingTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Employee.class, EmployeeGroup.class };
}
@Test
public void testCompositeTypeBinding() {
Session session = openSession();
session.beginTransaction();
EmployeeGroup employeegroup = new EmployeeGroup( new EmployeeGroupId( "a", "b" ) );
employeegroup.addEmployee( new Employee( "stliu" ) );
employeegroup.addEmployee( new Employee( "david" ) );
session.save( employeegroup );
employeegroup = new EmployeeGroup( new EmployeeGroupId( "c", "d" ) );
employeegroup.addEmployee( new Employee( "gail" ) );
employeegroup.addEmployee( new Employee( "steve" ) );
session.save( employeegroup );
session.getTransaction().commit();
session.close();
session = openSession();
List<EmployeeGroupId> parameters = new ArrayList<EmployeeGroupId>();
parameters.add( new EmployeeGroupId( "a", "b" ) );
parameters.add( new EmployeeGroupId( "c", "d" ) );
parameters.add( new EmployeeGroupId( "e", "f" ) );
List result = session.createQuery( "select eg from EmployeeGroup eg where eg.id in (:employeegroupIds)" )
.setParameterList( "employeegroupIds", parameters ).list();
Assert.assertEquals( 2, result.size() );
employeegroup = (EmployeeGroup) result.get( 0 );
Assert.assertEquals( "a", employeegroup.getId().getGroupName() );
Assert.assertNotNull( employeegroup.getEmployees() );
Assert.assertEquals( 2, employeegroup.getEmployees().size() );
session.close();
}
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. 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 Inc.
*
* 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.subselect;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
@GeneratedValue
private Long id;
private String name;
public String getName() {
return name;
}
@SuppressWarnings("unused")
private Employee() {
}
public Employee(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@ -0,0 +1,70 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. 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 Inc.
*
* 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.subselect;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
@Entity
public class EmployeeGroup {
@Id
private EmployeeGroupId id;
@OneToMany(cascade = CascadeType.ALL)
@Fetch(FetchMode.SUBSELECT)
private List<Employee> employees = new ArrayList<Employee>();
public EmployeeGroup(EmployeeGroupId id) {
this.id = id;
}
@SuppressWarnings("unused")
private EmployeeGroup() {
}
public boolean addEmployee(Employee employee) {
return employees.add(employee);
}
public List<Employee> getEmployees() {
return employees;
}
public EmployeeGroupId getId() {
return id;
}
@Override
public String toString() {
return id.toString();
}
}

View File

@ -0,0 +1,58 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. 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 Inc.
*
* 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.subselect;
import java.io.Serializable;
import javax.persistence.Embeddable;
@Embeddable
public class EmployeeGroupId
implements Serializable {
private static final long serialVersionUID = 1L;
private String groupName;
private String departmentName;
@SuppressWarnings("unused")
private EmployeeGroupId() {
}
public EmployeeGroupId(String groupName, String departmentName) {
this.groupName = groupName;
this.departmentName = departmentName;
}
public String getDepartmentName() {
return departmentName;
}
public String getGroupName() {
return groupName;
}
@Override
public String toString() {
return "groupName: " + groupName + ", departmentName: " + departmentName;
}
}