From d35ee1a82bf0fdf2de2724a02619eea1cf3c98bd Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 23 Jul 2020 14:01:03 +0200 Subject: [PATCH] DATAJPA-872 - Polishing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use QueryHints interface where possible and MutableQueryHints only inside of method implementations to hide mutability. Introduce QueryHints.from(…) as factory method to obtain a merged view of QueryHints. Reorganize imports, reformat code, add Javadoc. Fix license header in test. Fix generics. Original pull request: #426. --- .../repository/query/AbstractJpaQuery.java | 5 +- .../data/jpa/repository/query/Jpa21Utils.java | 9 +- .../support/CrudMethodMetadata.java | 13 +-- .../CrudMethodMetadataPostProcessor.java | 22 +++-- .../repository/support/DefaultQueryHints.java | 21 +++-- .../repository/support/MutableQueryHints.java | 86 +++++++++++++++++++ .../jpa/repository/support/QueryHints.java | 38 +++++++- .../repository/support/SimpleQueryHints.java | 54 ------------ .../support/DefaultQueryHintsTest.java | 6 +- .../support/MutableQueryHintsUnitTests.java | 76 ++++++++++++++++ .../support/SimpleJpaRepositoryUnitTests.java | 3 +- .../support/SimpleQueryHintsUnitTests.java | 69 --------------- 12 files changed, 235 insertions(+), 167 deletions(-) create mode 100644 src/main/java/org/springframework/data/jpa/repository/support/MutableQueryHints.java delete mode 100644 src/main/java/org/springframework/data/jpa/repository/support/SimpleQueryHints.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/support/MutableQueryHintsUnitTests.java delete mode 100644 src/test/java/org/springframework/data/jpa/repository/support/SimpleQueryHintsUnitTests.java diff --git a/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java index 541f9dd0b..acd2f142f 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java @@ -41,8 +41,7 @@ import org.springframework.data.jpa.repository.query.JpaQueryExecution.Procedure import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEntityExecution; import org.springframework.data.jpa.repository.query.JpaQueryExecution.SlicedExecution; import org.springframework.data.jpa.repository.query.JpaQueryExecution.StreamExecution; -import org.springframework.data.jpa.repository.support.QueryHintValue; -import org.springframework.data.jpa.repository.support.SimpleQueryHints; +import org.springframework.data.jpa.repository.support.QueryHints; import org.springframework.data.jpa.util.JpaMetamodel; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; @@ -241,7 +240,7 @@ public abstract class AbstractJpaQuery implements RepositoryQuery { JpaEntityGraph entityGraph = method.getEntityGraph(); if (entityGraph != null) { - SimpleQueryHints hints = Jpa21Utils.getFetchGraphHint(em, method.getEntityGraph(), + QueryHints hints = Jpa21Utils.getFetchGraphHint(em, method.getEntityGraph(), getQueryMethod().getEntityInformation().getJavaType()); hints.forEach(query::setHint); diff --git a/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java b/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java index 850d916c2..03ce1bbda 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java @@ -19,7 +19,6 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import javax.persistence.AttributeNode; import javax.persistence.EntityGraph; @@ -27,8 +26,8 @@ import javax.persistence.EntityManager; import javax.persistence.Query; import javax.persistence.Subgraph; -import org.springframework.data.jpa.repository.support.QueryHintValue; -import org.springframework.data.jpa.repository.support.SimpleQueryHints; +import org.springframework.data.jpa.repository.support.MutableQueryHints; +import org.springframework.data.jpa.repository.support.QueryHints; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -65,10 +64,10 @@ public class Jpa21Utils { // prevent instantiation } - public static SimpleQueryHints getFetchGraphHint(EntityManager em, @Nullable JpaEntityGraph entityGraph, + public static QueryHints getFetchGraphHint(EntityManager em, @Nullable JpaEntityGraph entityGraph, Class entityType) { - SimpleQueryHints result = new SimpleQueryHints(); + MutableQueryHints result = new MutableQueryHints(); if (entityGraph == null) { return result; diff --git a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java index 018104fb3..586de904f 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java @@ -16,12 +16,7 @@ package org.springframework.data.jpa.repository.support; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.function.BiConsumer; import javax.persistence.LockModeType; @@ -50,19 +45,19 @@ public interface CrudMethodMetadata { /** * Returns all query hints in a list to be applied to queries executed for the CRUD method. - * + * * @return * @since 2.4 */ - SimpleQueryHints getQueryHints(); + QueryHints getQueryHints(); /** * Returns all query hints in a list to be applied to queries executed for the CRUD method. - * + * * @return * @since 2.4 */ - SimpleQueryHints getQueryHintsForCount(); + QueryHints getQueryHintsForCount(); /** * Returns the {@link EntityGraph} to be used. diff --git a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java index 0973e0eb0..b7700277e 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java @@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.support; import java.lang.reflect.Method; import java.util.HashSet; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -191,8 +190,8 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B private static class DefaultCrudMethodMetadata implements CrudMethodMetadata { private final @Nullable LockModeType lockModeType; - private final SimpleQueryHints queryHints; - private final SimpleQueryHints queryHintsForCount; + private final org.springframework.data.jpa.repository.support.QueryHints queryHints; + private final org.springframework.data.jpa.repository.support.QueryHints queryHintsForCount; private final Optional entityGraph; private final Method method; @@ -223,9 +222,10 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B return annotation == null ? null : (LockModeType) AnnotationUtils.getValue(annotation); } - private static SimpleQueryHints findQueryHints(Method method, Predicate annotationFilter) { + private static org.springframework.data.jpa.repository.support.QueryHints findQueryHints(Method method, + Predicate annotationFilter) { - SimpleQueryHints queryHints = new SimpleQueryHints(); + MutableQueryHints queryHints = new MutableQueryHints(); QueryHints queryHintsAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, QueryHints.class); @@ -255,13 +255,21 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B return lockModeType; } + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.CrudMethodMetadata#getQueryHints() + */ @Override - public SimpleQueryHints getQueryHints() { + public org.springframework.data.jpa.repository.support.QueryHints getQueryHints() { return queryHints; } + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.CrudMethodMetadata#getQueryHintsForCount() + */ @Override - public SimpleQueryHints getQueryHintsForCount() { + public org.springframework.data.jpa.repository.support.QueryHints getQueryHintsForCount() { return queryHintsForCount; } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/DefaultQueryHints.java b/src/main/java/org/springframework/data/jpa/repository/support/DefaultQueryHints.java index 904b6f069..45f5c1e02 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/DefaultQueryHints.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/DefaultQueryHints.java @@ -93,26 +93,25 @@ class DefaultQueryHints implements QueryHints { return new DefaultQueryHints(this.information, this.metadata, this.entityManager, true); } + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.QueryHints#forEach(java.util.function.BiConsumer) + */ @Override - public void forEach(BiConsumer consumer) { - combineHints().forEach(consumer); + public void forEach(BiConsumer action) { + combineHints().forEach(action); } - private SimpleQueryHints combineHints() { - - SimpleQueryHints hints = forCounts ? metadata.getQueryHintsForCount() : metadata.getQueryHints(); - - hints.addAll(getFetchGraphs()); - - return hints; + private QueryHints combineHints() { + return QueryHints.from(forCounts ? metadata.getQueryHintsForCount() : metadata.getQueryHints(), getFetchGraphs()); } - private SimpleQueryHints getFetchGraphs() { + private QueryHints getFetchGraphs() { return Optionals .mapIfAllPresent(entityManager, metadata.getEntityGraph(), (em, graph) -> Jpa21Utils.getFetchGraphHint(em, getEntityGraph(graph), information.getJavaType())) - .orElse(new SimpleQueryHints()); + .orElse(new MutableQueryHints()); } private JpaEntityGraph getEntityGraph(EntityGraph entityGraph) { diff --git a/src/main/java/org/springframework/data/jpa/repository/support/MutableQueryHints.java b/src/main/java/org/springframework/data/jpa/repository/support/MutableQueryHints.java new file mode 100644 index 000000000..7dd56897a --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/support/MutableQueryHints.java @@ -0,0 +1,86 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.support; + +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + +import javax.persistence.EntityManager; + +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * Mutable implementation of {@link QueryHints}, without the Option to switch between + * {@link #forCounts()}/{@link #withFetchGraphs(EntityManager)} hints. + * + * @author Jens Schauder + * @author Mark Paluch + * @since 2.4 + * @see QueryHints + */ +public class MutableQueryHints implements QueryHints { + + private final MultiValueMap values = new LinkedMultiValueMap<>(); + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.QueryHints#withFetchGraphs(javax.persistence.EntityManager) + */ + @Override + public QueryHints withFetchGraphs(EntityManager em) { + return this; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.QueryHints#forCounts() + */ + @Override + public QueryHints forCounts() { + return this; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.QueryHints#forEach(java.util.function.BiConsumer) + */ + @Override + public void forEach(BiConsumer action) { + + for (Map.Entry> entry : values.entrySet()) { + + for (Object value : entry.getValue()) { + action.accept(entry.getKey(), value); + } + } + } + + /** + * Add a new key-value pair for a hint. + * + * @param name + * @param value + */ + public void add(String name, Object value) { + values.add(name, value); + } + + MultiValueMap getValues() { + return values; + } +} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/QueryHints.java b/src/main/java/org/springframework/data/jpa/repository/support/QueryHints.java index b147a92e0..3e0748872 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/QueryHints.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/QueryHints.java @@ -19,6 +19,8 @@ import java.util.function.BiConsumer; import javax.persistence.EntityManager; +import org.springframework.util.Assert; + /** * QueryHints provides access to query hints defined via {@link CrudMethodMetadata#getQueryHints()} QueryHintList()} by * default excluding JPA {@link javax.persistence.EntityGraph}. The object allows to switch between query hints for @@ -29,7 +31,27 @@ import javax.persistence.EntityManager; * @author Jens Schauder * @since 2.0 */ -interface QueryHints { +public interface QueryHints { + + /** + * Create a new {@link QueryHints} object from the given {@code sources}. + * + * @param sources must not be {@literal null}. + * @return a merged representation of {@link QueryHints QueryHints}. + * @since 2.4 + */ + static QueryHints from(QueryHints... sources) { + + Assert.notNull(sources, "Sources must not be null!"); + + MutableQueryHints result = new MutableQueryHints(); + + for (QueryHints queryHints : sources) { + queryHints.forEach(result.getValues()::add); + } + + return result; + } /** * Creates and returns a new {@link QueryHints} instance including {@link javax.persistence.EntityGraph}. @@ -49,12 +71,16 @@ interface QueryHints { QueryHints forCounts(); /** + * Performs the given action for each element of this query hints object until all hints have been processed or the + * action throws an exception. Actions are performed in the order of iteration, if that order is specified. Exceptions + * thrown by the action are relayed to the caller. + *

* Passes each query hint to the consumer. Query hint keys might appear more than once. * - * @param consumer to process query hints consisting of a key and a value. + * @param action to process query hints consisting of a key and a value. * @since 2.4 */ - void forEach(BiConsumer consumer); + void forEach(BiConsumer action); /** * Null object implementation of {@link QueryHints}. @@ -84,7 +110,11 @@ interface QueryHints { return this; } + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.QueryHints#forEach(java.util.function.BiConsumer) + */ @Override - public void forEach(BiConsumer consumer) {} + public void forEach(BiConsumer action) {} } } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleQueryHints.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleQueryHints.java deleted file mode 100644 index 10aff1f1e..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleQueryHints.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.jpa.repository.support; - -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; - -/** - * Just the values of QueryHints, without the Option to switch between count/ fetchGraph hints. - * - * @author Jens Schauder - * @since 2.4 - * @see QueryHints - */ -public class SimpleQueryHints { - - MultiValueMap values = new LinkedMultiValueMap<>(); - - - public void add(String name, Object value) { - values.add(name, value); - } - - public void forEach(BiConsumer consumer) { - - for (Map.Entry> entry : values.entrySet()) { - - for (Object value : entry.getValue()) { - consumer.accept(entry.getKey(), value); - } - } - } - - public void addAll(SimpleQueryHints hints) { - hints.forEach(this::add); - } -} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/DefaultQueryHintsTest.java b/src/test/java/org/springframework/data/jpa/repository/support/DefaultQueryHintsTest.java index 98f7b1326..2eecbedd6 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/DefaultQueryHintsTest.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/DefaultQueryHintsTest.java @@ -18,9 +18,7 @@ package org.springframework.data.jpa.repository.support; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.junit.Before; @@ -75,7 +73,7 @@ public class DefaultQueryHintsTest { private void setupMainHints() { - SimpleQueryHints mainHints = new SimpleQueryHints(); + MutableQueryHints mainHints = new MutableQueryHints(); mainHints.add("name1", "value1"); mainHints.add("name2", "value2"); @@ -84,7 +82,7 @@ public class DefaultQueryHintsTest { private void setUpCountHints() { - SimpleQueryHints countHints = new SimpleQueryHints(); + MutableQueryHints countHints = new MutableQueryHints(); countHints.add("n1", "1"); countHints.add("n2", "2"); diff --git a/src/test/java/org/springframework/data/jpa/repository/support/MutableQueryHintsUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/MutableQueryHintsUnitTests.java new file mode 100644 index 000000000..0838c0780 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/support/MutableQueryHintsUnitTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.support; + +import static org.assertj.core.api.Assertions.*; + +import java.util.ArrayList; +import java.util.List; + +import org.assertj.core.api.Assertions; +import org.junit.Test; + +import org.springframework.data.util.Pair; + +/** + * Unit tests for {@link MutableQueryHints}. + * + * @author Jens Schauder + * @author Mark Paluch + */ +public class MutableQueryHintsUnitTests { + + @Test // DATAJPA-872 + public void emptyQueryHint() { + new MutableQueryHints().forEach((k, v) -> Assertions.fail("Empty SimpleQueryHints shouldn't contain a value")); + } + + @Test // DATAJPA-872 + public void queryHint() { + + MutableQueryHints hints = new MutableQueryHints(); + hints.add("key", "value"); + hints.add("key", "other value"); + hints.add("other key", "another value"); + + List calls = new ArrayList<>(); + hints.forEach((k, v) -> calls.add(Pair.of(k, v))); + + assertThat(calls).containsExactlyInAnyOrder(Pair.of("key", "value"), Pair.of("key", "other value"), + Pair.of("other key", "another value")); + } + + @Test // DATAJPA-872 + public void shouldMergeQueryHints() { + + MutableQueryHints hints = new MutableQueryHints(); + hints.add("key", "value"); + hints.add("key", "other value"); + hints.add("other key", "another value"); + + MutableQueryHints additionalHints = new MutableQueryHints(); + additionalHints.add("key", "23"); + additionalHints.add("another key", "42"); + + QueryHints merged = QueryHints.from(hints, additionalHints); + + List calls = new ArrayList<>(); + merged.forEach((k, v) -> calls.add(Pair.of(k, v))); + + assertThat(calls).containsExactlyInAnyOrder(Pair.of("key", "value"), Pair.of("key", "other value"),Pair.of("key", "23"), + Pair.of("other key", "another value"), Pair.of("another key", "42")); + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java index cc649efd6..df68272c1 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java @@ -32,6 +32,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.sample.User; @@ -76,7 +77,7 @@ public class SimpleJpaRepositoryUnitTests { when(em.createQuery(criteriaQuery)).thenReturn(query); when(em.createQuery(countCriteriaQuery)).thenReturn(countQuery); - SimpleQueryHints hints = new SimpleQueryHints(); + MutableQueryHints hints = new MutableQueryHints(); when(metadata.getQueryHints()).thenReturn(hints); when(metadata.getQueryHintsForCount()).thenReturn(hints); diff --git a/src/test/java/org/springframework/data/jpa/repository/support/SimpleQueryHintsUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/SimpleQueryHintsUnitTests.java deleted file mode 100644 index 99d887d95..000000000 --- a/src/test/java/org/springframework/data/jpa/repository/support/SimpleQueryHintsUnitTests.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.springframework.data.jpa.repository.support;/* - * Copyright 2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import static org.assertj.core.api.Assertions.*; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.springframework.data.util.Pair; - -public class SimpleQueryHintsUnitTests { - - @Test - public void emptyQueryHint() { - new SimpleQueryHints().forEach((k, v) -> Assertions.fail("Empty SimpleQueryHints shouldn't contain a value")); - } - - @Test - public void queryHint() { - - SimpleQueryHints hints = new SimpleQueryHints(); - hints.add("key", "value"); - hints.add("key", "other value"); - hints.add("other key", "another value"); - - List calls = new ArrayList(); - hints.forEach((k, v) -> calls.add(Pair.of(k, v))); - - assertThat(calls).containsExactlyInAnyOrder(Pair.of("key", "value"), Pair.of("key", "other value"), - Pair.of("other key", "another value")); - } - - @Test - public void addingQueryHints() { - - SimpleQueryHints hints = new SimpleQueryHints(); - hints.add("key", "value"); - hints.add("key", "other value"); - hints.add("other key", "another value"); - - SimpleQueryHints additionalHints = new SimpleQueryHints(); - additionalHints.add("key", "23"); - additionalHints.add("another key", "42"); - - hints.addAll(additionalHints); - - List calls = new ArrayList(); - hints.forEach((k, v) -> calls.add(Pair.of(k, v))); - - assertThat(calls).containsExactlyInAnyOrder(Pair.of("key", "value"), Pair.of("key", "other value"),Pair.of("key", "23"), - Pair.of("other key", "another value"), Pair.of("another key", "42")); - } - -}