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
|
||||
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
|
||||
final Iterator itr = aliasedLockOptions.getAliasLockIterator();
|
||||
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.
|
||||
* @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();
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ public class SybaseASE157Dialect extends SybaseASE15Dialect {
|
|||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
public class ColumnNameCache {
|
||||
private static final float LOAD_FACTOR = .75f;
|
||||
|
||||
private final Map<String, Integer> columnNameToIndexCache;
|
||||
private final ConcurrentHashMap<String, Integer> columnNameToIndexCache;
|
||||
|
||||
/**
|
||||
* Constructs a ColumnNameCache
|
||||
|
|
|
@ -69,6 +69,7 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.IdentitySet;
|
||||
import org.hibernate.loader.hql.QueryLoader;
|
||||
import org.hibernate.param.ParameterSpecification;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -101,7 +102,7 @@ public class QueryTranslatorImpl implements FilterTranslator {
|
|||
private String sql;
|
||||
|
||||
private ParameterTranslations paramTranslations;
|
||||
private List collectedParameterSpecifications;
|
||||
private List<ParameterSpecification> collectedParameterSpecifications;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -569,12 +570,11 @@ public class QueryTranslatorImpl implements FilterTranslator {
|
|||
public ParameterTranslations getParameterTranslations() {
|
||||
if ( paramTranslations == null ) {
|
||||
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
|
||||
// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications );
|
||||
}
|
||||
return paramTranslations;
|
||||
}
|
||||
|
||||
public List getCollectedParameterSpecifications() {
|
||||
public List<ParameterSpecification> getCollectedParameterSpecifications() {
|
||||
return collectedParameterSpecifications;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
|
|||
private SessionFactoryImplementor sessionFactory;
|
||||
private LinkedList<SqlWriter> outputStack = new LinkedList<SqlWriter>();
|
||||
private final ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
|
||||
private List collectedParameters = new ArrayList();
|
||||
private List<ParameterSpecification> collectedParameters = new ArrayList<ParameterSpecification>();
|
||||
|
||||
|
||||
// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -106,7 +106,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
|
|||
LOG.trace( prefix + ruleName );
|
||||
}
|
||||
|
||||
public List getCollectedParameters() {
|
||||
public List<ParameterSpecification> getCollectedParameters() {
|
||||
return collectedParameters;
|
||||
}
|
||||
|
||||
|
|
|
@ -452,16 +452,12 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
|
|||
this.alias = alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getSqlFragment() {
|
||||
return persisterDiscriminatorMetadata.getSqlFragment( alias );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Type getResolutionType() {
|
||||
return persisterDiscriminatorMetadata.getResolutionType();
|
||||
}
|
||||
|
@ -660,21 +656,24 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
|
|||
|
||||
|
||||
// ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
private List embeddedParameters;
|
||||
private List<ParameterSpecification> embeddedParameters;
|
||||
|
||||
@Override
|
||||
public void addEmbeddedParameter(ParameterSpecification specification) {
|
||||
if ( embeddedParameters == null ) {
|
||||
embeddedParameters = new ArrayList();
|
||||
embeddedParameters = new ArrayList<ParameterSpecification>();
|
||||
}
|
||||
embeddedParameters.add( specification );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEmbeddedParameters() {
|
||||
return embeddedParameters != null && ! embeddedParameters.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterSpecification[] getEmbeddedParameters() {
|
||||
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
|
||||
return embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
|
||||
}
|
||||
|
||||
public ParameterSpecification getIndexCollectionSelectorParamSpec() {
|
||||
|
|
|
@ -147,14 +147,14 @@ public class IndexNode extends FromReferenceNode {
|
|||
}
|
||||
String selectorExpression = gen.getSQL();
|
||||
joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression );
|
||||
List paramSpecs = gen.getCollectedParameters();
|
||||
List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
|
||||
if ( paramSpecs != null ) {
|
||||
switch ( paramSpecs.size() ) {
|
||||
case 0 :
|
||||
// nothing to do
|
||||
break;
|
||||
case 1 :
|
||||
ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecs.get( 0 );
|
||||
ParameterSpecification paramSpec = paramSpecs.get( 0 );
|
||||
paramSpec.setExpectedType( queryableCollection.getIndexType() );
|
||||
fromElement.setIndexCollectionSelectorParamSpec( paramSpec );
|
||||
break;
|
||||
|
@ -176,39 +176,40 @@ public class IndexNode extends FromReferenceNode {
|
|||
* In the (rare?) case where the index selector contains multiple parameters...
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
|
||||
throws SQLException {
|
||||
int bindCount = 0;
|
||||
Iterator itr = paramSpecs.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final ParameterSpecification paramSpec = ( ParameterSpecification ) itr.next();
|
||||
for ( ParameterSpecification paramSpec : paramSpecs ) {
|
||||
bindCount += paramSpec.bind( statement, qp, session, position + bindCount );
|
||||
}
|
||||
return bindCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpectedType(Type expectedType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderDisplayInfo() {
|
||||
return "index-selector [" + collectDisplayInfo() + "]" ;
|
||||
}
|
||||
|
||||
private String collectDisplayInfo() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
Iterator itr = paramSpecs.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
buffer.append( ( ( ParameterSpecification ) itr.next() ).renderDisplayInfo() );
|
||||
for ( ParameterSpecification paramSpec : paramSpecs ) {
|
||||
buffer.append( ( paramSpec ).renderDisplayInfo() );
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.FetchingScrollableResultsImpl;
|
||||
import org.hibernate.internal.ScrollableResultsImpl;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.loader.spi.AfterLoadAction;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -110,7 +111,7 @@ import org.hibernate.type.VersionType;
|
|||
public abstract class Loader {
|
||||
|
||||
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 ColumnNameCache columnNameCache;
|
||||
|
||||
|
@ -931,9 +932,9 @@ public abstract class Loader {
|
|||
EntityKey[] keys = new EntityKey[entitySpan]; //we can reuse it for each row
|
||||
LOG.trace( "Processing result set" );
|
||||
int count;
|
||||
boolean isDebugEnabled = LOG.isDebugEnabled();
|
||||
|
||||
for ( count = 0; count < maxRows && rs.next(); count++ ) {
|
||||
if ( isDebugEnabled )
|
||||
if ( DEBUG_ENABLED )
|
||||
LOG.debugf( "Result set row: %s", count );
|
||||
Object result = getRowFromResultSet(
|
||||
rs,
|
||||
|
@ -975,8 +976,10 @@ public abstract class Loader {
|
|||
|
||||
protected boolean hasSubselectLoadableCollections() {
|
||||
final Loadable[] loadables = getEntityPersisters();
|
||||
for (int i=0; i<loadables.length; i++ ) {
|
||||
if ( loadables[i].hasSubselectLoadableCollections() ) return true;
|
||||
for ( Loadable loadable : loadables ) {
|
||||
if ( loadable.hasSubselectLoadableCollections() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -985,8 +988,8 @@ public abstract class Loader {
|
|||
Set[] result = new Set[ ( ( EntityKey[] ) keys.get(0) ).length ];
|
||||
for ( int j=0; j<result.length; j++ ) {
|
||||
result[j] = new HashSet( keys.size() );
|
||||
for ( int i=0; i<keys.size(); i++ ) {
|
||||
result[j].add( ( ( EntityKey[] ) keys.get(i) ) [j] );
|
||||
for ( Object key : keys ) {
|
||||
result[j].add( ( (EntityKey[]) key )[j] );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -1032,13 +1035,11 @@ public abstract class Loader {
|
|||
private Map buildNamedParameterLocMap(QueryParameters queryParameters) {
|
||||
if ( queryParameters.getNamedParameters()!=null ) {
|
||||
final Map namedParameterLocMap = new HashMap();
|
||||
Iterator piter = queryParameters.getNamedParameters().keySet().iterator();
|
||||
while ( piter.hasNext() ) {
|
||||
String name = (String) piter.next();
|
||||
for(String name : queryParameters.getNamedParameters().keySet()){
|
||||
namedParameterLocMap.put(
|
||||
name,
|
||||
getNamedParameterLocs(name)
|
||||
);
|
||||
);
|
||||
}
|
||||
return namedParameterLocMap;
|
||||
}
|
||||
|
@ -1992,30 +1993,33 @@ public abstract class Loader {
|
|||
*/
|
||||
protected int bindNamedParameters(
|
||||
final PreparedStatement statement,
|
||||
final Map namedParams,
|
||||
final Map<String, TypedValue> namedParams,
|
||||
final int startIndex,
|
||||
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;
|
||||
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;
|
||||
}
|
||||
int result = 0;
|
||||
if ( CollectionHelper.isEmpty( namedParams ) ) {
|
||||
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) {
|
||||
|
@ -2080,7 +2084,7 @@ public abstract class Loader {
|
|||
|
||||
private ColumnNameCache retreiveColumnNameToIndexCache(ResultSet rs) throws SQLException {
|
||||
if ( columnNameCache == null ) {
|
||||
LOG.trace( "Building columnName->columnIndex cache" );
|
||||
LOG.trace( "Building columnName -> columnIndex cache" );
|
||||
columnNameCache = new ColumnNameCache( rs.getMetaData().getColumnCount() );
|
||||
}
|
||||
|
||||
|
@ -2293,7 +2297,7 @@ public abstract class Loader {
|
|||
final Serializable[] ids,
|
||||
final Object[] parameterValues,
|
||||
final Type[] parameterTypes,
|
||||
final Map namedParameters,
|
||||
final Map<String, TypedValue> namedParameters,
|
||||
final Type type) throws HibernateException {
|
||||
|
||||
Type[] idTypes = new Type[ids.length];
|
||||
|
@ -2551,7 +2555,6 @@ public abstract class Loader {
|
|||
// whether scrolling of their result set should be 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.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -47,15 +48,15 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
|
|||
private final Serializable[] keys;
|
||||
private final Type[] types;
|
||||
private final Object[] values;
|
||||
private final Map namedParameters;
|
||||
private final Map namedParameterLocMap;
|
||||
private final Map<String, TypedValue> namedParameters;
|
||||
private final Map<String, int[]> namedParameterLocMap;
|
||||
|
||||
public SubselectCollectionLoader(
|
||||
QueryableCollection persister,
|
||||
String subquery,
|
||||
Collection entityKeys,
|
||||
QueryParameters queryParameters,
|
||||
Map namedParameterLocMap,
|
||||
Map<String, int[]> namedParameterLocMap,
|
||||
SessionFactoryImplementor factory,
|
||||
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||
super( persister, 1, subquery, factory, loadQueryInfluencers );
|
||||
|
@ -74,6 +75,7 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(Serializable id, SessionImplementor session)
|
||||
throws HibernateException {
|
||||
loadCollectionSubselect(
|
||||
|
@ -86,8 +88,9 @@ public class SubselectCollectionLoader extends BasicCollectionLoader {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
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.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -47,15 +48,15 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
|
|||
private final Serializable[] keys;
|
||||
private final Type[] types;
|
||||
private final Object[] values;
|
||||
private final Map namedParameters;
|
||||
private final Map namedParameterLocMap;
|
||||
private final Map<String, TypedValue> namedParameters;
|
||||
private final Map<String, int[]> namedParameterLocMap;
|
||||
|
||||
public SubselectOneToManyLoader(
|
||||
QueryableCollection persister,
|
||||
String subquery,
|
||||
Collection entityKeys,
|
||||
QueryParameters queryParameters,
|
||||
Map namedParameterLocMap,
|
||||
Map<String, int[]> namedParameterLocMap,
|
||||
SessionFactoryImplementor factory,
|
||||
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||
super( persister, 1, subquery, factory, loadQueryInfluencers );
|
||||
|
@ -73,6 +74,7 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
|
|||
this.namedParameterLocMap = namedParameterLocMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(Serializable id, SessionImplementor session) throws HibernateException {
|
||||
loadCollectionSubselect(
|
||||
session,
|
||||
|
@ -83,9 +85,9 @@ public class SubselectOneToManyLoader extends OneToManyLoader {
|
|||
getKeyType()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 ) {
|
||||
return new int[] { ( ( Integer ) loc ).intValue() };
|
||||
return new int[] { (Integer) loc };
|
||||
}
|
||||
else {
|
||||
return ArrayHelper.toIntArray( ( List ) loc );
|
||||
|
|
|
@ -88,7 +88,7 @@ public class QueryLoader extends BasicLoader {
|
|||
//private Type[] sqlResultTypes;
|
||||
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 int[] owners;
|
||||
|
@ -209,15 +209,15 @@ public class QueryLoader extends BasicLoader {
|
|||
public final void validateScrollability() throws HibernateException {
|
||||
queryTranslator.validateScrollability();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsFetchingScroll() {
|
||||
return queryTranslator.containsCollectionFetches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loadable[] getEntityPersisters() {
|
||||
return entityPersisters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return sqlAliases;
|
||||
}
|
||||
|
@ -225,15 +225,15 @@ public class QueryLoader extends BasicLoader {
|
|||
public String[] getSqlAliasSuffixes() {
|
||||
return sqlAliasSuffixes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSuffixes() {
|
||||
return getSqlAliasSuffixes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCollectionSuffixes() {
|
||||
return collectionSuffixes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getQueryIdentifier() {
|
||||
return queryTranslator.getQueryIdentifier();
|
||||
}
|
||||
|
@ -241,6 +241,7 @@ public class QueryLoader extends BasicLoader {
|
|||
/**
|
||||
* The SQL query string to be called.
|
||||
*/
|
||||
@Override
|
||||
public String 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
|
||||
* return a non-null value
|
||||
*/
|
||||
@Override
|
||||
protected CollectionPersister[] getCollectionPersisters() {
|
||||
return collectionPersisters;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getCollectionOwners() {
|
||||
return collectionOwners;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean[] getEntityEagerPropertyFetches() {
|
||||
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
|
||||
* to the entity at the given index (-1 if there is no "owner")
|
||||
*/
|
||||
@Override
|
||||
protected int[] getOwners() {
|
||||
return owners;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EntityType[] getOwnerAssociationTypes() {
|
||||
return ownerAssociationTypes;
|
||||
}
|
||||
|
||||
// -- Loader overrides --
|
||||
|
||||
@Override
|
||||
protected boolean isSubselectLoadingEnabled() {
|
||||
return hasSubselectLoadableCollections();
|
||||
}
|
||||
|
@ -282,6 +285,7 @@ public class QueryLoader extends BasicLoader {
|
|||
/**
|
||||
* @param lockOptions a collection of lock modes specified dynamically via the Query interface
|
||||
*/
|
||||
@Override
|
||||
protected LockMode[] getLockModes(LockOptions lockOptions) {
|
||||
if ( lockOptions == null ) {
|
||||
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
|
||||
// as the ultimate output of this section...
|
||||
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.setTimeOut( lockOptions.getTimeOut() );
|
||||
|
||||
final Iterator itr = sqlAliasByEntityAlias.entrySet().iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Map.Entry entry = (Map.Entry) itr.next();
|
||||
final String userAlias = (String) entry.getKey();
|
||||
final String drivingSqlAlias = (String) entry.getValue();
|
||||
for ( Map.Entry<String, String> entry : sqlAliasByEntityAlias.entrySet() ) {
|
||||
final String userAlias = entry.getKey();
|
||||
final String drivingSqlAlias = entry.getValue();
|
||||
if ( drivingSqlAlias == null ) {
|
||||
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
|
||||
// want to apply the lock against the root table (for all other strategies,
|
||||
// it just happens that driving and root are the same).
|
||||
final QueryNode select = ( QueryNode ) queryTranslator.getSqlAST();
|
||||
final Lockable drivingPersister = ( Lockable ) select.getFromClause()
|
||||
final QueryNode select = (QueryNode) queryTranslator.getSqlAST();
|
||||
final Lockable drivingPersister = (Lockable) select.getFromClause()
|
||||
.findFromElementByUserOrSqlAlias( userAlias, drivingSqlAlias )
|
||||
.getQueryable();
|
||||
final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
|
||||
|
@ -377,7 +379,7 @@ public class QueryLoader extends BasicLoader {
|
|||
// apply the collected locks and columns
|
||||
return dialect.applyLocksToSql( sql, locks, keyColumnNames );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyPostLoadLocks(Object[] row, LockMode[] lockModesArray, SessionImplementor session) {
|
||||
// todo : scalars???
|
||||
// if ( row.length != lockModesArray.length ) {
|
||||
|
@ -393,7 +395,7 @@ public class QueryLoader extends BasicLoader {
|
|||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean upgradeLocks() {
|
||||
return true;
|
||||
}
|
||||
|
@ -401,18 +403,18 @@ public class QueryLoader extends BasicLoader {
|
|||
private boolean hasSelectNew() {
|
||||
return aggregatedSelectExpression != null && aggregatedSelectExpression.getResultTransformer() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getResultRowAliases() {
|
||||
return queryReturnAliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResultTransformer resolveResultTransformer(ResultTransformer resultTransformer) {
|
||||
final ResultTransformer implicitResultTransformer = aggregatedSelectExpression == null
|
||||
? null
|
||||
: aggregatedSelectExpression.getResultTransformer();
|
||||
return HolderInstantiator.resolveResultTransformer( implicitResultTransformer, resultTransformer );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean[] includeInResultRow() {
|
||||
boolean[] includeInResultTuple = includeInSelect;
|
||||
if ( hasScalars ) {
|
||||
|
@ -421,7 +423,7 @@ public class QueryLoader extends BasicLoader {
|
|||
}
|
||||
return includeInResultTuple;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SessionImplementor session)
|
||||
throws SQLException, HibernateException {
|
||||
|
||||
|
@ -433,6 +435,7 @@ public class QueryLoader extends BasicLoader {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object[] getResultRow(Object[] row, ResultSet rs, SessionImplementor session)
|
||||
throws SQLException, HibernateException {
|
||||
Object[] resultRow;
|
||||
|
@ -450,6 +453,8 @@ public class QueryLoader extends BasicLoader {
|
|||
return resultRow;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException {
|
||||
// meant to handle dynamic instantiation queries...
|
||||
HolderInstantiator holderInstantiator = buildHolderInstantiator( resultTransformer );
|
||||
|
@ -579,6 +584,7 @@ public class QueryLoader extends BasicLoader {
|
|||
/**
|
||||
* Returns the locations of all occurrences of the named parameter.
|
||||
*/
|
||||
@Override
|
||||
public int[] getNamedParameterLocs(String name) throws QueryException {
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* @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.
|
||||
* @throws SQLException Indicates problems performing the binding.
|
||||
*/
|
||||
@Override
|
||||
protected int bindParameterValues(
|
||||
final PreparedStatement statement,
|
||||
final QueryParameters queryParameters,
|
||||
final int startIndex,
|
||||
final SessionImplementor session) throws SQLException {
|
||||
// int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
|
||||
int position = startIndex;
|
||||
// List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
|
||||
List parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
|
||||
Iterator itr = parameterSpecs.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
|
||||
List<ParameterSpecification> parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
|
||||
for ( ParameterSpecification spec : parameterSpecs ) {
|
||||
position += spec.bind( statement, queryParameters, session, position );
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getSourceLine() {
|
||||
return sourceLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getSourceColumn() {
|
||||
return sourceColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
return expectedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setExpectedType(Type expectedType) {
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
|
|
|
@ -55,9 +55,7 @@ public class CollectionFilterKeyParameterSpecification implements ParameterSpeci
|
|||
this.queryParameterPosition = queryParameterPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int bind(
|
||||
PreparedStatement statement,
|
||||
QueryParameters qp,
|
||||
|
@ -68,23 +66,17 @@ public class CollectionFilterKeyParameterSpecification implements ParameterSpeci
|
|||
return keyType.getColumnSpan( session.getFactory() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
return keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setExpectedType(Type expectedType) {
|
||||
// todo : throw exception?
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String renderDisplayInfo() {
|
||||
return "collection-filter-key=" + collectionRole;
|
||||
}
|
||||
|
|
|
@ -60,9 +60,7 @@ public class DynamicFilterParameterSpecification implements ParameterSpecificati
|
|||
this.definedParameterType = definedParameterType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int bind(
|
||||
PreparedStatement statement,
|
||||
QueryParameters qp,
|
||||
|
@ -85,23 +83,17 @@ public class DynamicFilterParameterSpecification implements ParameterSpecificati
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
return definedParameterType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setExpectedType(Type expectedType) {
|
||||
// todo : throw exception? maybe warn if not the same?
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String renderDisplayInfo() {
|
||||
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.hibernate.engine.spi.TypedValue;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
|
||||
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification {
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.hibernate.type.Type;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
|
||||
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification {
|
||||
private final int hqlPosition;
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.hibernate.type.VersionType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
|
||||
private VersionType type;
|
||||
private final VersionType type;
|
||||
|
||||
/**
|
||||
* Constructs a version seed parameter bind specification.
|
||||
|
@ -48,32 +48,24 @@ public class VersionTypeSeedParameterSpecification implements ParameterSpecifica
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
|
||||
throws SQLException {
|
||||
type.nullSafeSet( statement, type.seed( session ), position, session );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Type getExpectedType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setExpectedType(Type expectedType) {
|
||||
// expected type is intrinsic here...
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String renderDisplayInfo() {
|
||||
return "version-seed, type=" + type;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public class ForUpdateFragment {
|
|||
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 );
|
||||
LockMode upgradeType = null;
|
||||
Iterator iter = lockOptions.getAliasLockIterator();
|
||||
|
@ -68,13 +68,13 @@ public class ForUpdateFragment {
|
|||
if ( LockMode.READ.lessThan( lockMode ) ) {
|
||||
final String tableAlias = ( String ) me.getKey();
|
||||
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 ) {
|
||||
throw new IllegalArgumentException( "alias not found: " + tableAlias );
|
||||
}
|
||||
keyColumns = StringHelper.qualify( tableAlias, keyColumns );
|
||||
for ( int i = 0; i < keyColumns.length; i++ ) {
|
||||
addTableAlias( keyColumns[i] );
|
||||
for ( String keyColumn : keyColumns ) {
|
||||
addTableAlias( keyColumn );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -120,8 +120,8 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
int n = 0;
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
int[] subtypes = propertyTypes[i].sqlTypes( mapping );
|
||||
for ( int j = 0; j < subtypes.length; j++ ) {
|
||||
sqlTypes[n++] = subtypes[j];
|
||||
for ( int subtype : subtypes ) {
|
||||
sqlTypes[n++] = subtype;
|
||||
}
|
||||
}
|
||||
return sqlTypes;
|
||||
|
@ -327,7 +327,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
return old != null;
|
||||
}
|
||||
if ( old == null ) {
|
||||
return current != null;
|
||||
return true;
|
||||
}
|
||||
Object[] currentValues = getPropertyValues( current, session );
|
||||
Object[] oldValues = ( Object[] ) old;
|
||||
|
@ -344,12 +344,12 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
return resolve( hydrate( rs, names, session, owner ), session, owner );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int begin, SessionImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
|
@ -360,7 +360,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
begin += propertyTypes[i].getColumnSpan( session.getFactory() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(
|
||||
PreparedStatement st,
|
||||
Object value,
|
||||
|
@ -401,13 +401,13 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
return getPropertyValues( value, entityMode );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
return nullSafeGet( rs, new String[] {name}, session, owner );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object component, int i, SessionImplementor session)
|
||||
throws HibernateException {
|
||||
return getPropertyValue( component, i, entityMode );
|
||||
|
@ -417,12 +417,12 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
throws HibernateException {
|
||||
return componentTuplizer.getPropertyValue( component, i );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getPropertyValues(Object component, SessionImplementor session)
|
||||
throws HibernateException {
|
||||
return getPropertyValues( component, entityMode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getPropertyValues(Object component, EntityMode entityMode)
|
||||
throws HibernateException {
|
||||
if ( component instanceof Object[] ) {
|
||||
|
@ -435,40 +435,41 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
return componentTuplizer.getPropertyValues( component );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyValues(Object component, Object[] values, EntityMode entityMode)
|
||||
throws HibernateException {
|
||||
componentTuplizer.setPropertyValues( component, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getSubtypes() {
|
||||
return propertyTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "component" + ArrayHelper.toString( propertyNames );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLoggableString(Object value, SessionFactoryImplementor factory)
|
||||
throws HibernateException {
|
||||
if ( value == null ) {
|
||||
return "null";
|
||||
}
|
||||
Map result = new HashMap();
|
||||
|
||||
if ( entityMode == null ) {
|
||||
throw new ClassCastException( value.getClass().getName() );
|
||||
}
|
||||
Map<String,String> result = new HashMap<String, String>();
|
||||
Object[] values = getPropertyValues( value, entityMode );
|
||||
for ( int i = 0; i < propertyTypes.length; i++ ) {
|
||||
result.put( propertyNames[i], propertyTypes[i].toLoggableString( values[i], factory ) );
|
||||
}
|
||||
return StringHelper.unqualify( getName() ) + result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPropertyNames() {
|
||||
return propertyNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object component, SessionFactoryImplementor factory)
|
||||
throws HibernateException {
|
||||
if ( component == null ) {
|
||||
|
@ -491,7 +492,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object replace(
|
||||
Object original,
|
||||
Object target,
|
||||
|
@ -577,11 +578,11 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CascadeStyle getCascadeStyle(int i) {
|
||||
return cascade[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
@ -620,7 +621,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchMode getFetchMode(int i) {
|
||||
return joinedFetch[i];
|
||||
}
|
||||
|
@ -681,7 +682,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
//for components with many-to-one associations
|
||||
return resolve( value, session, owner );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getPropertyNullability() {
|
||||
return propertyNullability;
|
||||
}
|
||||
|
@ -690,15 +691,15 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
public boolean isXMLElement() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
|
||||
return xml;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException {
|
||||
replaceNode( node, ( Element ) value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] toColumnNullness(Object value, Mapping mapping) {
|
||||
boolean[] result = new boolean[ getColumnSpan( mapping ) ];
|
||||
if ( value == null ) {
|
||||
|
@ -713,7 +714,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmbedded() {
|
||||
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