HHH-10885 - Fix JPA Native Queries with ordinal parameter is zero based
This commit is contained in:
parent
e99270c332
commit
92f5032cc0
|
@ -824,23 +824,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
@Override
|
||||
public NativeQueryImplementor createNativeQuery(String sqlString) {
|
||||
checkOpen();
|
||||
checkTransactionSynchStatus();
|
||||
delayedAfterCompletion();
|
||||
|
||||
try {
|
||||
NativeQueryImpl query = new NativeQueryImpl(
|
||||
sqlString,
|
||||
false,
|
||||
this,
|
||||
getFactory().getQueryPlanCache().getSQLParameterMetadata( sqlString )
|
||||
);
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
return query;
|
||||
}
|
||||
catch ( RuntimeException he ) {
|
||||
throw exceptionConverter.convert( he );
|
||||
}
|
||||
final NativeQueryImpl query = (NativeQueryImpl) createSQLQuery( sqlString );
|
||||
query.setZeroBasedParametersIndex( false );
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -891,12 +877,31 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
@Override
|
||||
public NativeQueryImplementor createSQLQuery(String queryString) {
|
||||
return createNativeQuery( queryString );
|
||||
checkOpen();
|
||||
checkTransactionSynchStatus();
|
||||
delayedAfterCompletion();
|
||||
|
||||
try {
|
||||
NativeQueryImpl query = new NativeQueryImpl(
|
||||
queryString,
|
||||
false,
|
||||
this,
|
||||
getFactory().getQueryPlanCache().getSQLParameterMetadata( queryString )
|
||||
);
|
||||
query.setComment( "dynamic native SQL query" );
|
||||
return query;
|
||||
}
|
||||
catch ( RuntimeException he ) {
|
||||
throw exceptionConverter.convert( he );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQueryImplementor getNamedSQLQuery(String name) {
|
||||
return getNamedNativeQuery( name );
|
||||
final NativeQueryImpl nativeQuery = (NativeQueryImpl) getNamedNativeQuery( name );
|
||||
nativeQuery.setZeroBasedParametersIndex( true );
|
||||
return nativeQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@ import javax.persistence.Parameter;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ParameterMetadata {
|
||||
|
||||
/**
|
||||
* Does this parameter set contain any named parameters?
|
||||
*
|
||||
|
@ -52,4 +53,11 @@ public interface ParameterMetadata {
|
|||
<T> QueryParameter<T> getQueryParameter(Integer position);
|
||||
|
||||
<T> QueryParameter<T> resolve(Parameter<T> param);
|
||||
|
||||
default boolean isOrdinalParametersZeroBased() {
|
||||
return true;
|
||||
}
|
||||
|
||||
default void setOrdinalParametersZeroBased(boolean isZeroBased) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,10 @@ public class NativeQueryImpl<T> extends AbstractProducedQuery<T> implements Nati
|
|||
return this;
|
||||
}
|
||||
|
||||
public void setZeroBasedParametersIndex(boolean zeroBasedParametersIndex) {
|
||||
getParameterMetadata().setOrdinalParametersZeroBased( zeroBasedParametersIndex );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return sqlString;
|
||||
|
|
|
@ -31,6 +31,7 @@ public class ParameterMetadataImpl implements ParameterMetadata {
|
|||
|
||||
private final OrdinalParameterDescriptor[] ordinalDescriptors;
|
||||
private final Map<String,NamedParameterDescriptor> namedDescriptorMap;
|
||||
private boolean isOrdinalParametersZeroBased = true;
|
||||
|
||||
/**
|
||||
* Instantiates a ParameterMetadata container.
|
||||
|
@ -116,6 +117,9 @@ public class ParameterMetadataImpl implements ParameterMetadata {
|
|||
* @throws QueryParameterException If the position is out of range
|
||||
*/
|
||||
public OrdinalParameterDescriptor getOrdinalParameterDescriptor(int position) {
|
||||
if ( !isOrdinalParametersZeroBased ) {
|
||||
position--;
|
||||
}
|
||||
if ( position < 0 || position >= ordinalDescriptors.length ) {
|
||||
throw new QueryParameterException(
|
||||
"Position beyond number of declared ordinal parameters. " +
|
||||
|
@ -239,4 +243,13 @@ public class ParameterMetadataImpl implements ParameterMetadata {
|
|||
return getNamedParameterDescriptor( name ).getSourceLocations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrdinalParametersZeroBased() {
|
||||
return isOrdinalParametersZeroBased;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrdinalParametersZeroBased(boolean isZeroBased) {
|
||||
this.isOrdinalParametersZeroBased = isZeroBased;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,31 +197,35 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
|||
}
|
||||
|
||||
public QueryParameterBinding getBinding(int position) {
|
||||
int positionAdjustment = 0;
|
||||
if ( !parameterMetadata.isOrdinalParametersZeroBased() ) {
|
||||
positionAdjustment = -1;
|
||||
}
|
||||
QueryParameterBinding binding = null;
|
||||
if ( parameterMetadata != null ) {
|
||||
if ( ! parameterMetadata.hasPositionalParameters() ) {
|
||||
if ( !parameterMetadata.hasPositionalParameters() ) {
|
||||
// no positional parameters, assume jpa named.
|
||||
binding = locateBinding( Integer.toString( position ) );
|
||||
}
|
||||
else {
|
||||
try {
|
||||
if ( position < positionalParameterBindings.size() ) {
|
||||
binding = positionalParameterBindings.get( position );
|
||||
if ( position + positionAdjustment < positionalParameterBindings.size() ) {
|
||||
binding = positionalParameterBindings.get( position + positionAdjustment );
|
||||
if ( binding == null ) {
|
||||
binding = makeBinding( parameterMetadata.getQueryParameter( position ) );
|
||||
positionalParameterBindings.set( position, binding );
|
||||
binding = makeBinding( parameterMetadata.getQueryParameter( position ) );
|
||||
positionalParameterBindings.set( position + positionAdjustment, binding );
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( int i = 0; i < position - positionalParameterBindings.size(); i++ ) {
|
||||
for ( int i = 0; i < position + positionAdjustment - positionalParameterBindings.size(); i++ ) {
|
||||
positionalParameterBindings.add( null );
|
||||
}
|
||||
QueryParameter queryParameter = parameterMetadata.getQueryParameter( position );
|
||||
QueryParameter queryParameter = parameterMetadata.getQueryParameter( position );
|
||||
binding = makeBinding( queryParameter );
|
||||
positionalParameterBindings.add( binding );
|
||||
}
|
||||
}
|
||||
catch ( QueryParameterException e ) {
|
||||
catch (QueryParameterException e) {
|
||||
// treat this as null binding
|
||||
}
|
||||
}
|
||||
|
@ -247,8 +251,18 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
|||
}
|
||||
}
|
||||
// verify position parameters bound
|
||||
for ( int i = 0; i < positionalParameterBindings.size(); i++ ) {
|
||||
final QueryParameterBinding binding = positionalParameterBindings.get( i );
|
||||
int startIndex = 0;
|
||||
if ( !parameterMetadata.isOrdinalParametersZeroBased() ) {
|
||||
startIndex = 1;
|
||||
}
|
||||
for ( int i = startIndex; i < positionalParameterBindings.size(); i++ ) {
|
||||
QueryParameterBinding binding = null;
|
||||
if ( parameterMetadata.isOrdinalParametersZeroBased() ) {
|
||||
binding = positionalParameterBindings.get( i );
|
||||
}
|
||||
else {
|
||||
binding = positionalParameterBindings.get( i - 1 );
|
||||
}
|
||||
if ( binding == null || !binding.isBound() ) {
|
||||
throw new QueryException( "Positional parameter [" + i + "] not set" );
|
||||
}
|
||||
|
@ -282,7 +296,6 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
|||
if ( bindType == null ) {
|
||||
bindType = SerializableType.INSTANCE;
|
||||
}
|
||||
Object object = binding.getBindValue();
|
||||
positionalValueSpan += bindType.getColumnSpan( sessionFactory );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue