From 2d58a8d2fd88b647f2395b249bea33532054e67c Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Fri, 11 Sep 2020 15:21:23 +0200 Subject: [PATCH] DATAGRAPH-1374 - Add support for sliced queries. --- .../repository/query/AbstractNeo4jQuery.java | 32 ++++++++++++------- .../integration/imperative/RepositoryIT.java | 13 ++++++++ .../repositories/PersonRepository.java | 3 ++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java b/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java index aa7376fc3..e836cac1b 100644 --- a/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java +++ b/src/main/java/org/springframework/data/neo4j/repository/query/AbstractNeo4jQuery.java @@ -18,9 +18,12 @@ package org.springframework.data.neo4j.repository.query; import java.util.Collections; import java.util.List; import java.util.function.BiFunction; +import java.util.function.LongSupplier; import org.neo4j.driver.Record; import org.neo4j.driver.types.TypeSystem; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.SliceImpl; import org.springframework.data.neo4j.core.Neo4jOperations; import org.springframework.data.neo4j.core.PreparedQuery; import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext; @@ -42,7 +45,8 @@ abstract class AbstractNeo4jQuery extends Neo4jQuerySupport implements Repositor protected final Neo4jOperations neo4jOperations; - AbstractNeo4jQuery(Neo4jOperations neo4jOperations, Neo4jMappingContext mappingContext, Neo4jQueryMethod queryMethod, + AbstractNeo4jQuery(Neo4jOperations neo4jOperations, Neo4jMappingContext mappingContext, + Neo4jQueryMethod queryMethod, Neo4jQueryType queryType) { super(mappingContext, queryMethod, queryType); @@ -66,23 +70,29 @@ abstract class AbstractNeo4jQuery extends Neo4jQuerySupport implements Repositor getInputProperties(resultProcessor), parameterAccessor, null, getMappingFunction(resultProcessor)); Object rawResult = new Neo4jQueryExecution.DefaultQueryExecution(neo4jOperations).execute(preparedQuery, - queryMethod.isCollectionLikeQuery() || queryMethod.isPageQuery()); + queryMethod.isCollectionLikeQuery() || queryMethod.isPageQuery() || queryMethod.isSliceQuery()); Object processedResult = resultProcessor.processResult(rawResult, OptionalUnwrappingConverter.INSTANCE); - if (!queryMethod.isPageQuery()) { - return processedResult; - } else { - return PageableExecutionUtils.getPage((List) processedResult, parameterAccessor.getPageable(), () -> { + LongSupplier totalSupplier = () -> { - PreparedQuery countQuery = prepareQuery(Long.class, Collections.emptyList(), parameterAccessor, - Neo4jQueryType.COUNT, null); - return neo4jOperations.toExecutableQuery(countQuery).getRequiredSingleResult(); - }); + PreparedQuery countQuery = prepareQuery(Long.class, Collections.emptyList(), parameterAccessor, + Neo4jQueryType.COUNT, null); + return neo4jOperations.toExecutableQuery(countQuery).getRequiredSingleResult(); + }; + if (queryMethod.isPageQuery()) { + return PageableExecutionUtils.getPage((List) processedResult, parameterAccessor.getPageable(), totalSupplier); + } else if (queryMethod.isSliceQuery()) { + long total = totalSupplier.getAsLong(); + Pageable pageable = parameterAccessor.getPageable(); + return new SliceImpl<>((List) processedResult, pageable, pageable.getOffset() + pageable.getPageSize() < total); + } else { + return processedResult; } } protected abstract PreparedQuery prepareQuery(Class returnedType, - List includedProperties, Neo4jParameterAccessor parameterAccessor, @Nullable Neo4jQueryType queryType, + List includedProperties, Neo4jParameterAccessor parameterAccessor, + @Nullable Neo4jQueryType queryType, @Nullable BiFunction mappingFunction); } diff --git a/src/test/java/org/springframework/data/neo4j/integration/imperative/RepositoryIT.java b/src/test/java/org/springframework/data/neo4j/integration/imperative/RepositoryIT.java index 060852b85..7f4d07a27 100644 --- a/src/test/java/org/springframework/data/neo4j/integration/imperative/RepositoryIT.java +++ b/src/test/java/org/springframework/data/neo4j/integration/imperative/RepositoryIT.java @@ -67,6 +67,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.geo.Box; import org.springframework.data.geo.Circle; @@ -537,6 +538,18 @@ class RepositoryIT { List persons = repository.findAllByNameOrName(TEST_PERSON1_NAME, TEST_PERSON2_NAME); assertThat(persons).containsExactlyInAnyOrder(person1, person2); } + + @Test // DATAGRAPH-1374 + void findSliceShouldWork(@Autowired PersonRepository repository) { + + Slice slice = repository.findSliceByNameOrName(TEST_PERSON1_NAME, TEST_PERSON2_NAME, PageRequest.of(0, 1, Sort.by("name").descending())); + assertThat(slice.get()).hasSize(1).extracting("name").containsExactly(TEST_PERSON2_NAME); + assertThat(slice.hasNext()).isTrue(); + + slice = repository.findSliceByNameOrName(TEST_PERSON1_NAME, TEST_PERSON2_NAME, slice.nextPageable()); + assertThat(slice.get()).hasSize(1).extracting("name").containsExactly(TEST_PERSON1_NAME); + assertThat(slice.hasNext()).isFalse(); + } } @Nested diff --git a/src/test/java/org/springframework/data/neo4j/integration/imperative/repositories/PersonRepository.java b/src/test/java/org/springframework/data/neo4j/integration/imperative/repositories/PersonRepository.java index 4357697f2..b6b2d81d7 100644 --- a/src/test/java/org/springframework/data/neo4j/integration/imperative/repositories/PersonRepository.java +++ b/src/test/java/org/springframework/data/neo4j/integration/imperative/repositories/PersonRepository.java @@ -25,6 +25,7 @@ import org.neo4j.driver.types.Point; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Range; +import org.springframework.data.domain.Slice; import org.springframework.data.geo.Box; import org.springframework.data.geo.Circle; import org.springframework.data.geo.Distance; @@ -109,6 +110,8 @@ public interface PersonRepository extends Neo4jRepository findAllByNameOrName(String aName, String anotherName, Pageable pageable); + Slice findSliceByNameOrName(String aName, String anotherName, Pageable pageable); + Long countAllByNameOrName(String aName, String anotherName); Optional findOneByNameAndFirstNameAllIgnoreCase(String name, String firstName);