Add support for Limit.

Closes #3052
This commit is contained in:
Mark Paluch
2023-07-05 11:25:02 +02:00
parent 30c32f7452
commit 133ec27b74
6 changed files with 42 additions and 11 deletions

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.data.jpa.repository.query;
import jakarta.persistence.TemporalType;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import jakarta.persistence.TemporalType;
import org.springframework.core.MethodParameter;
import org.springframework.data.jpa.repository.Temporal;
import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter;
@@ -60,6 +60,13 @@ public class JpaParameters extends Parameters<JpaParameters, JpaParameter> {
return new JpaParameters(parameters);
}
/**
* @return {@code true} if the method signature declares Limit or Pageable parameters.
*/
public boolean hasLimitingParameters() {
return hasLimitParameter() || hasPageableParameter();
}
/**
* Custom {@link Parameter} implementation adding parameters of type {@link Temporal} to the special ones.
*

View File

@@ -79,7 +79,7 @@ final class NamedQuery extends AbstractJpaQuery {
this.declaredQuery = DeclaredQuery.of(queryString, false);
boolean weNeedToCreateCountQuery = !namedCountQueryIsPresent && method.getParameters().hasPageableParameter();
boolean weNeedToCreateCountQuery = !namedCountQueryIsPresent && method.getParameters().hasLimitingParameters();
boolean cantExtractQuery = !extractor.canExtractQuery();
if (weNeedToCreateCountQuery && cantExtractQuery) {

View File

@@ -96,7 +96,7 @@ public class ParameterBinder {
bind(query, metadata, accessor);
if (!useJpaForPaging || !parameters.hasPageableParameter() || accessor.getPageable().isUnpaged()) {
if (!useJpaForPaging || !parameters.hasLimitingParameters() || accessor.getPageable().isUnpaged()) {
return query;
}

View File

@@ -29,11 +29,14 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.jpa.domain.sample.Role;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.provider.PersistenceProvider;
@@ -53,6 +56,7 @@ import org.springframework.transaction.annotation.Transactional;
* @author Oliver Gierke
* @author Krzysztof Krason
* @author Greg Turnquist
* @author Mark Paluch
* @see QueryLookupStrategy
*/
@ExtendWith(SpringExtension.class)
@@ -221,6 +225,23 @@ class UserRepositoryFinderTests {
assertThat(slice.hasNext()).isFalse();
}
@Test // DATAJPA-94
void executesQueryWithLimitAndScrollPosition() {
Window<User> first = userRepository.findByLastnameOrderByFirstname(Limit.of(1), //
ScrollPosition.offset(), //
"Matthews" //
);
Window<User> next = userRepository.findByLastnameOrderByFirstname(Limit.of(1), //
ScrollPosition.offset(1), //
"Matthews" //
);
assertThat(first).containsExactly(dave);
assertThat(next).containsExactly(oliver);
}
@Test // DATAJPA-830
void executesMethodWithNotContainingOnStringCorrectly() {

View File

@@ -15,13 +15,9 @@
*/
package org.springframework.data.jpa.repository.query;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import jakarta.persistence.LockModeType;
import jakarta.persistence.QueryHint;
@@ -159,6 +155,8 @@ class JpaQueryMethodUnitTests {
@Test
void rejectsInvalidReturntypeOnPagebleFinder() {
when(metadata.getReturnedDomainClass(any())).thenReturn((Class) User.class);
assertThatIllegalStateException()
.isThrownBy(() -> new JpaQueryMethod(invalidReturnType, metadata, factory, extractor));
}
@@ -166,6 +164,8 @@ class JpaQueryMethodUnitTests {
@Test
void rejectsPageableAndSortInFinderMethod() {
when(metadata.getReturnedDomainClass(any())).thenReturn((Class) User.class);
assertThatIllegalStateException()
.isThrownBy(() -> new JpaQueryMethod(pageableAndSort, metadata, factory, extractor));
}

View File

@@ -26,6 +26,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@@ -226,6 +227,8 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
Page<User> findByLastnameIgnoringCase(Pageable pageable, String lastname);
Window<User> findByLastnameOrderByFirstname(Limit limit, ScrollPosition scrollPosition, String lastname);
List<User> findByLastnameIgnoringCaseLike(String lastname);
List<User> findByLastnameAndFirstnameAllIgnoringCase(String lastname, String firstname);