HHH-13310 getParameterValue() not working for collections

This commit is contained in:
Andrea Boriero 2020-10-29 10:19:32 +00:00
parent 36f9360a31
commit 096916e6fa
3 changed files with 101 additions and 33 deletions

View File

@ -25,6 +25,11 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.Spliterator; import java.util.Spliterator;
import java.util.Spliterators; import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import javax.persistence.CacheRetrieveMode; import javax.persistence.CacheRetrieveMode;
@ -752,58 +757,105 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@Override @Override
public <T> T getParameterValue(Parameter<T> parameter) { public <T> T getParameterValue(Parameter<T> parameter) {
LOGGER.tracef( "#getParameterValue(%s)", parameter ); LOGGER.tracef( "#getParameterValue(%s)", parameter );
getProducer().checkOpen( false ); getProducer().checkOpen( false );
if ( !getParameterMetadata().containsReference( (QueryParameter) parameter ) ) { return (T) getParameterValue(
throw new IllegalArgumentException( "Parameter reference [" + parameter + "] did not come from this query" ); (QueryParameter) parameter,
(queryParameter) -> new IllegalStateException( "Parameter value not yet bound : " + queryParameter.toString() ),
(queryParameter, e) -> {
final String message = "Parameter reference [" + queryParameter + "] did not come from this query";
if ( e == null ) {
return new IllegalArgumentException( message );
} }
return new IllegalArgumentException( message, e );
final QueryParameterBinding<T> binding = getQueryParameterBindings().getBinding( (QueryParameter<T>) parameter ); },
LOGGER.debugf( "Checking whether parameter reference [%s] is bound : %s", parameter, binding.isBound() ); (queryParameter, isBound) -> LOGGER.debugf(
if ( !binding.isBound() ) { "Checking whether parameter reference [%s] is bound : %s",
throw new IllegalStateException( "Parameter value not yet bound : " + parameter.toString() ); queryParameter,
} isBound
return binding.getBindValue(); )
);
} }
@Override @Override
public Object getParameterValue(String name) { public Object getParameterValue(String name) {
getProducer().checkOpen( false ); getProducer().checkOpen( false );
final QueryParameterBinding binding; final QueryParameter<Object> queryParameter = getParameterMetadata().getQueryParameter( name );
try { return getParameterValue(
binding = getQueryParameterBindings().getBinding( name ); queryParameter,
(parameter) -> new IllegalStateException( "Parameter value not yet bound : " + parameter.getName() ),
(parameter, e) -> {
final String message = "Could not resolve parameter by name - " + parameter.getName();
if ( e == null ) {
return new IllegalArgumentException( message );
} }
catch (QueryParameterException e) { return new IllegalArgumentException( message, e );
throw new IllegalArgumentException( "Could not resolve parameter by name - " + name, e ); },
} (parameter, isBound) -> LOGGER.debugf(
"Checking whether positional named [%s] is bound : %s",
LOGGER.debugf( "Checking whether named parameter [%s] is bound : %s", name, binding.isBound() ); parameter.getName(),
if ( !binding.isBound() ) { isBound
throw new IllegalStateException( "Parameter value not yet bound : " + name ); )
} );
return binding.getBindValue();
} }
@Override @Override
public Object getParameterValue(int position) { public Object getParameterValue(int position) {
getProducer().checkOpen( false ); getProducer().checkOpen( false );
final QueryParameterBinding binding; final QueryParameter<Object> queryParameter = getParameterMetadata().getQueryParameter( position );
try { return getParameterValue(
binding = getQueryParameterBindings().getBinding( position ); queryParameter,
(parameter) -> new IllegalStateException( "Parameter value not yet bound : " + parameter.getPosition() ),
(parameter, e) -> {
String message = "Could not resolve parameter by position - " + parameter.getPosition();
if ( e == null ) {
return new IllegalArgumentException( message );
} }
catch (QueryParameterException e) { return new IllegalArgumentException( message, e );
throw new IllegalArgumentException( "Could not resolve parameter by position - " + position, e ); },
(parameter, isBound) -> LOGGER.debugf(
"Checking whether positional parameter [%s] is bound : %s",
parameter.getPosition(),
isBound
)
);
} }
LOGGER.debugf( "Checking whether positional parameter [%s] is bound : %s", (Integer) position, (Boolean) binding.isBound() ); private Object getParameterValue(
if ( !binding.isBound() ) { QueryParameter queryParameter,
throw new IllegalStateException( "Parameter value not yet bound : " + position ); Function<QueryParameter, IllegalStateException> notBoundParamenterException,
BiFunction<QueryParameter, QueryParameterException, IllegalArgumentException> couldNotResolveParameterException,
BiConsumer<QueryParameter, Boolean> boundCheckingLogger) {
try {
final QueryParameterBindings parameterBindings = getQueryParameterBindings();
if ( queryParameter == null ) {
throw couldNotResolveParameterException.apply( queryParameter, null );
}
if ( parameterBindings.isMultiValuedBinding( queryParameter ) ) {
final QueryParameterListBinding<Object> queryParameterListBinding = parameterBindings
.getQueryParameterListBinding( queryParameter );
final Collection<Object> bindValues = queryParameterListBinding.getBindValues();
if ( bindValues == null ) {
throw notBoundParamenterException.apply( queryParameter );
}
return bindValues;
}
final QueryParameterBinding<Object> binding = parameterBindings.getBinding( queryParameter );
final boolean bound = binding.isBound();
boundCheckingLogger.accept( queryParameter, bound );
if ( !bound ) {
throw notBoundParamenterException.apply( queryParameter );
} }
return binding.getBindValue(); return binding.getBindValue();
} }
catch (QueryParameterException e) {
throw couldNotResolveParameterException.apply( queryParameter, e );
}
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -317,6 +317,14 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
// return values.toArray( new Object[values.size()] ); // return values.toArray( new Object[values.size()] );
} }
@Override
public boolean isMultiValuedBinding(QueryParameter parameter) {
if ( parameterListBindingMap == null ) {
return false;
}
return parameterListBindingMap.containsKey( parameter );
}
/** /**
* @deprecated (since 5.2) expect a different approach to org.hibernate.engine.spi.QueryParameters in 6.0 * @deprecated (since 5.2) expect a different approach to org.hibernate.engine.spi.QueryParameters in 6.0
*/ */

View File

@ -35,4 +35,12 @@ public interface QueryParameterBindings {
Type[] collectPositionalBindTypes(); Type[] collectPositionalBindTypes();
Object[] collectPositionalBindValues(); Object[] collectPositionalBindValues();
Map<String,TypedValue> collectNamedParameterBindings(); Map<String,TypedValue> collectNamedParameterBindings();
/**
* @deprecated expect a different approach to org.hibernate.engine.spi.QueryParameters in 6.0
*/
@Deprecated
default boolean isMultiValuedBinding(QueryParameter parameter) {
return false;
}
} }