HHH-11121 - Wrong NativeQueryImpl.setZeroBasedParametersIndex when Session#createSQLQuery is executed after EM#createNativeQuery
This commit is contained in:
parent
47e925ead4
commit
306c151fff
|
@ -64,7 +64,7 @@ public class QueryPlanCache implements Serializable {
|
|||
* Used solely for caching param metadata for native-sql queries, see {@link #getSQLParameterMetadata} for a
|
||||
* discussion as to why...
|
||||
*/
|
||||
private final BoundedConcurrentHashMap<String,ParameterMetadataImpl> parameterMetadataCache;
|
||||
private final BoundedConcurrentHashMap<ParameterMetadataKey,ParameterMetadataImpl> parameterMetadataCache;
|
||||
|
||||
|
||||
private NativeQueryInterpreter nativeQueryInterpreterService;
|
||||
|
@ -102,7 +102,7 @@ public class QueryPlanCache implements Serializable {
|
|||
}
|
||||
|
||||
queryPlanCache = new BoundedConcurrentHashMap( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
|
||||
parameterMetadataCache = new BoundedConcurrentHashMap<String, ParameterMetadataImpl>(
|
||||
parameterMetadataCache = new BoundedConcurrentHashMap<>(
|
||||
maxParameterMetadataCount,
|
||||
20,
|
||||
BoundedConcurrentHashMap.Eviction.LIRS
|
||||
|
@ -121,11 +121,12 @@ public class QueryPlanCache implements Serializable {
|
|||
* @param query The query
|
||||
* @return The parameter metadata
|
||||
*/
|
||||
public ParameterMetadata getSQLParameterMetadata(final String query) {
|
||||
ParameterMetadataImpl value = parameterMetadataCache.get( query );
|
||||
public ParameterMetadata getSQLParameterMetadata(final String query, boolean isOrdinalParameterZeroBased) {
|
||||
final ParameterMetadataKey key = new ParameterMetadataKey( query, isOrdinalParameterZeroBased );
|
||||
ParameterMetadataImpl value = parameterMetadataCache.get( key );
|
||||
if ( value == null ) {
|
||||
value = nativeQueryInterpreterService.getParameterMetadata( query );
|
||||
parameterMetadataCache.putIfAbsent( query, value );
|
||||
parameterMetadataCache.putIfAbsent( key, value );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -227,6 +228,41 @@ public class QueryPlanCache implements Serializable {
|
|||
parameterMetadataCache.clear();
|
||||
}
|
||||
|
||||
private static class ParameterMetadataKey implements Serializable {
|
||||
private final String query;
|
||||
private final boolean isOrdinalParameterZeroBased;
|
||||
private final int hashCode;
|
||||
|
||||
public ParameterMetadataKey(String query, boolean isOrdinalParameterZeroBased) {
|
||||
this.query = query;
|
||||
this.isOrdinalParameterZeroBased = isOrdinalParameterZeroBased;
|
||||
int hash = query.hashCode();
|
||||
hash = 29 * hash + ( isOrdinalParameterZeroBased ? 1 : 0 );
|
||||
this.hashCode = hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ParameterMetadataKey that = (ParameterMetadataKey) o;
|
||||
|
||||
return isOrdinalParameterZeroBased == that.isOrdinalParameterZeroBased
|
||||
&& query.equals( that.query );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
private static class HQLQueryPlanKey implements Serializable {
|
||||
private final String query;
|
||||
private final boolean shallow;
|
||||
|
|
|
@ -554,7 +554,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
// then as a native query
|
||||
final NamedSQLQueryDefinition nativeQueryDefinition = factory.getNamedQueryRepository().getNamedSQLQueryDefinition( name );
|
||||
if ( nativeQueryDefinition != null ) {
|
||||
return createNativeQuery( nativeQueryDefinition );
|
||||
return createNativeQuery( nativeQueryDefinition, true );
|
||||
}
|
||||
|
||||
throw exceptionConverter.convert( new IllegalArgumentException( "No query defined for that name [" + name + "]" ) );
|
||||
|
@ -579,10 +579,17 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
return query;
|
||||
}
|
||||
|
||||
private NativeQueryImplementor createNativeQuery(NamedSQLQueryDefinition queryDefinition) {
|
||||
private NativeQueryImplementor createNativeQuery(NamedSQLQueryDefinition queryDefinition, boolean isOrdinalParameterZeroBased) {
|
||||
final ParameterMetadata parameterMetadata = factory.getQueryPlanCache().getSQLParameterMetadata(
|
||||
queryDefinition.getQueryString()
|
||||
queryDefinition.getQueryString(),
|
||||
isOrdinalParameterZeroBased
|
||||
);
|
||||
return getNativeQueryImplementor( queryDefinition, parameterMetadata );
|
||||
}
|
||||
|
||||
private NativeQueryImplementor getNativeQueryImplementor(
|
||||
NamedSQLQueryDefinition queryDefinition,
|
||||
ParameterMetadata parameterMetadata) {
|
||||
final NativeQueryImpl query = new NativeQueryImpl(
|
||||
queryDefinition,
|
||||
this,
|
||||
|
@ -761,7 +768,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
final NativeQueryImpl query = new NativeQueryImpl(
|
||||
queryDefinition,
|
||||
this,
|
||||
factory.getQueryPlanCache().getSQLParameterMetadata( queryDefinition.getQueryString() )
|
||||
factory.getQueryPlanCache().getSQLParameterMetadata( queryDefinition.getQueryString(), false )
|
||||
);
|
||||
query.setHibernateFlushMode( queryDefinition.getFlushMode() );
|
||||
query.setComment( queryDefinition.getComment() != null ? queryDefinition.getComment() : queryDefinition.getName() );
|
||||
|
@ -836,7 +843,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
@Override
|
||||
public NativeQueryImplementor createNativeQuery(String sqlString) {
|
||||
final NativeQueryImpl query = (NativeQueryImpl) createSQLQuery( sqlString );
|
||||
final NativeQueryImpl query = (NativeQueryImpl) getNativeQueryImplementor( sqlString, false );
|
||||
query.setZeroBasedParametersIndex( false );
|
||||
return query;
|
||||
}
|
||||
|
@ -881,7 +888,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
final NamedSQLQueryDefinition nativeQueryDefinition = factory.getNamedQueryRepository().getNamedSQLQueryDefinition( name );
|
||||
if ( nativeQueryDefinition != null ) {
|
||||
return createNativeQuery( nativeQueryDefinition );
|
||||
return createNativeQuery( nativeQueryDefinition, true );
|
||||
}
|
||||
|
||||
throw exceptionConverter.convert( new IllegalArgumentException( "No query defined for that name [" + name + "]" ) );
|
||||
|
@ -889,6 +896,12 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
@Override
|
||||
public NativeQueryImplementor createSQLQuery(String queryString) {
|
||||
return getNativeQueryImplementor( queryString, true );
|
||||
}
|
||||
|
||||
protected NativeQueryImplementor getNativeQueryImplementor(
|
||||
String queryString,
|
||||
boolean isOrdinalParameterZeroBased) {
|
||||
checkOpen();
|
||||
checkTransactionSynchStatus();
|
||||
delayedAfterCompletion();
|
||||
|
@ -898,7 +911,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
queryString,
|
||||
false,
|
||||
this,
|
||||
getFactory().getQueryPlanCache().getSQLParameterMetadata( queryString )
|
||||
getFactory().getQueryPlanCache().getSQLParameterMetadata( queryString, isOrdinalParameterZeroBased )
|
||||
);
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
return query;
|
||||
|
@ -906,9 +919,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
catch ( RuntimeException he ) {
|
||||
throw exceptionConverter.convert( he );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NativeQueryImplementor getNamedSQLQuery(String name) {
|
||||
final NativeQueryImpl nativeQuery = (NativeQueryImpl) getNamedNativeQuery( name );
|
||||
|
|
Loading…
Reference in New Issue