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.Spliterator;
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.StreamSupport;
import javax.persistence.CacheRetrieveMode;
@ -752,58 +757,105 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@Override
public <T> T getParameterValue(Parameter<T> parameter) {
LOGGER.tracef( "#getParameterValue(%s)", parameter );
getProducer().checkOpen( false );
if ( !getParameterMetadata().containsReference( (QueryParameter) parameter ) ) {
throw new IllegalArgumentException( "Parameter reference [" + parameter + "] did not come from this query" );
return (T) getParameterValue(
(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 );
}
final QueryParameterBinding<T> binding = getQueryParameterBindings().getBinding( (QueryParameter<T>) parameter );
LOGGER.debugf( "Checking whether parameter reference [%s] is bound : %s", parameter, binding.isBound() );
if ( !binding.isBound() ) {
throw new IllegalStateException( "Parameter value not yet bound : " + parameter.toString() );
}
return binding.getBindValue();
return new IllegalArgumentException( message, e );
},
(queryParameter, isBound) -> LOGGER.debugf(
"Checking whether parameter reference [%s] is bound : %s",
queryParameter,
isBound
)
);
}
@Override
public Object getParameterValue(String name) {
getProducer().checkOpen( false );
final QueryParameterBinding binding;
try {
binding = getQueryParameterBindings().getBinding( name );
final QueryParameter<Object> queryParameter = getParameterMetadata().getQueryParameter( name );
return getParameterValue(
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) {
throw new IllegalArgumentException( "Could not resolve parameter by name - " + name, e );
}
LOGGER.debugf( "Checking whether named parameter [%s] is bound : %s", name, binding.isBound() );
if ( !binding.isBound() ) {
throw new IllegalStateException( "Parameter value not yet bound : " + name );
}
return binding.getBindValue();
return new IllegalArgumentException( message, e );
},
(parameter, isBound) -> LOGGER.debugf(
"Checking whether positional named [%s] is bound : %s",
parameter.getName(),
isBound
)
);
}
@Override
public Object getParameterValue(int position) {
getProducer().checkOpen( false );
final QueryParameterBinding binding;
try {
binding = getQueryParameterBindings().getBinding( position );
final QueryParameter<Object> queryParameter = getParameterMetadata().getQueryParameter( position );
return getParameterValue(
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) {
throw new IllegalArgumentException( "Could not resolve parameter by position - " + position, e );
return new IllegalArgumentException( message, 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() );
if ( !binding.isBound() ) {
throw new IllegalStateException( "Parameter value not yet bound : " + position );
private Object getParameterValue(
QueryParameter queryParameter,
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();
}
catch (QueryParameterException e) {
throw couldNotResolveParameterException.apply( queryParameter, e );
}
}
@Override
@SuppressWarnings("unchecked")

View File

@ -317,6 +317,14 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
// 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
*/

View File

@ -35,4 +35,12 @@ public interface QueryParameterBindings {
Type[] collectPositionalBindTypes();
Object[] collectPositionalBindValues();
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;
}
}