HHH-8312 - named parameters binding are not correct when used within subquery
This commit is contained in:
parent
6a71cbb991
commit
6cabc326b8
|
@ -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 );
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,9 +1035,7 @@ 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)
|
||||||
|
@ -1992,31 +1993,34 @@ 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 ) {
|
|
||||||
// assumes that types are all of span 1
|
|
||||||
Iterator iter = namedParams.entrySet().iterator();
|
|
||||||
final boolean debugEnabled = LOG.isDebugEnabled();
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
while ( iter.hasNext() ) {
|
if ( CollectionHelper.isEmpty( namedParams ) ) {
|
||||||
Map.Entry e = ( Map.Entry ) iter.next();
|
return result;
|
||||||
String name = ( String ) e.getKey();
|
}
|
||||||
TypedValue typedval = ( TypedValue ) e.getValue();
|
|
||||||
|
for ( String name : namedParams.keySet() ) {
|
||||||
|
TypedValue typedValue = namedParams.get( name );
|
||||||
|
int columnSpan = typedValue.getType().getColumnSpan( getFactory() );
|
||||||
int[] locs = getNamedParameterLocs( name );
|
int[] locs = getNamedParameterLocs( name );
|
||||||
for ( int i = 0; i < locs.length; i++ ) {
|
for ( int loc : locs ) {
|
||||||
if ( debugEnabled ) LOG.debugf( "bindNamedParameters() %s -> %s [%s]", typedval.getValue(), name, locs[i] + startIndex );
|
if ( DEBUG_ENABLED ) {
|
||||||
typedval.getType().nullSafeSet( statement, typedval.getValue(), locs[i] + startIndex, session );
|
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;
|
result += locs.length;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getNamedParameterLocs(String name) {
|
public int[] getNamedParameterLocs(String name) {
|
||||||
throw new AssertionFailure("no named parameters");
|
throw new AssertionFailure("no named parameters");
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 + "}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue