diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java index 06088bf56dda..a6eab2372c54 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java @@ -25,6 +25,11 @@ 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; @@ -749,57 +754,104 @@ public boolean isBound(Parameter parameter) { @Override public T getParameterValue(Parameter 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" ); - } - - final QueryParameterBinding binding = getQueryParameterBindings().getBinding( (QueryParameter) 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 (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 ); + } + 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 ); - } - 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(); + final QueryParameter 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 ); + } + 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; + final QueryParameter 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 ); + } + return new IllegalArgumentException( message, e ); + }, + (parameter, isBound) -> LOGGER.debugf( + "Checking whether positional parameter [%s] is bound : %s", + parameter.getPosition(), + isBound + ) + ); + } + + private Object getParameterValue( + QueryParameter queryParameter, + Function notBoundParamenterException, + BiFunction couldNotResolveParameterException, + BiConsumer boundCheckingLogger) { try { - binding = getQueryParameterBindings().getBinding( position ); + final QueryParameterBindings parameterBindings = getQueryParameterBindings(); + + if ( queryParameter == null ) { + throw couldNotResolveParameterException.apply( queryParameter, null ); + } + if ( parameterBindings.isMultiValuedBinding( queryParameter ) ) { + final QueryParameterListBinding queryParameterListBinding = parameterBindings + .getQueryParameterListBinding( queryParameter ); + final Collection bindValues = queryParameterListBinding.getBindValues(); + if ( bindValues == null ) { + throw notBoundParamenterException.apply( queryParameter ); + } + return bindValues; + } + + final QueryParameterBinding 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 new IllegalArgumentException( "Could not resolve parameter by position - " + position, e ); - } - - 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 ); + throw couldNotResolveParameterException.apply( queryParameter, e ); } - return binding.getBindValue(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java index f4ce65ebe05a..d5122e03ae63 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java @@ -317,6 +317,14 @@ public Object[] collectPositionalBindValues() { // 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 */ diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindings.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindings.java index 5eb46e9b269e..24667470fa1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindings.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindings.java @@ -35,4 +35,12 @@ public interface QueryParameterBindings { Type[] collectPositionalBindTypes(); Object[] collectPositionalBindValues(); Map collectNamedParameterBindings(); + + /** + * @deprecated expect a different approach to org.hibernate.engine.spi.QueryParameters in 6.0 + */ + @Deprecated + default boolean isMultiValuedBinding(QueryParameter parameter) { + return false; + } }