Skip to content

Commit f98c7b9

Browse files
christophstroblmp911de
authored andcommittedNov 2, 2023
Show how to use Limit with repository queries.
Add methods taking a Limit parameter to various samples. Original pull request: #672 Closes #671
1 parent e90be0c commit f98c7b9

File tree

13 files changed

+167
-0
lines changed

13 files changed

+167
-0
lines changed
 

‎cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicUserRepository.java

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.List;
1919

2020
import org.springframework.data.cassandra.repository.Query;
21+
import org.springframework.data.domain.Limit;
2122
import org.springframework.data.repository.CrudRepository;
2223

2324
/**
@@ -55,4 +56,13 @@ public interface BasicUserRepository extends CrudRepository<User, Long> {
5556
* @return
5657
*/
5758
List<User> findUsersByLastnameStartsWith(String lastnamePrefix);
59+
60+
/**
61+
* Same as {@link #findUsersByLastnameStartsWith(String)} but reducing the result size to a given {@link Limit}.
62+
*
63+
* @param lastnamePrefix
64+
* @param maxResults the maximum number of results returned.
65+
* @return
66+
*/
67+
List<User> findUsersByLastnameStartsWith(String lastnamePrefix, Limit maxResults);
5868
}

‎cassandra/example/src/main/java/example/springdata/cassandra/basic/User.java

+6
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,10 @@ public class User {
4343
public User(Long id) {
4444
this.setId(id);
4545
}
46+
47+
public User(Long id, String firstname, String lastname) {
48+
this.id = id;
49+
this.firstname = firstname;
50+
this.lastname = lastname;
51+
}
4652
}

‎cassandra/example/src/test/java/example/springdata/cassandra/basic/BasicUserRepositoryTests.java

+23
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import static org.assertj.core.api.Assertions.*;
1919
import static org.assertj.core.api.Assumptions.*;
2020

21+
import java.util.stream.LongStream;
22+
2123
import example.springdata.cassandra.util.CassandraKeyspace;
2224
import example.springdata.cassandra.util.CassandraVersion;
2325

@@ -26,6 +28,7 @@
2628

2729
import org.springframework.beans.factory.annotation.Autowired;
2830
import org.springframework.boot.test.context.SpringBootTest;
31+
import org.springframework.data.domain.Limit;
2932
import org.springframework.data.util.Version;
3033

3134
import com.datastax.oss.driver.api.core.CqlSession;
@@ -120,4 +123,24 @@ void findByDerivedQueryMethodWithSASI() throws InterruptedException {
120123

121124
assertThat(repository.findUsersByLastnameStartsWith("last")).contains(user);
122125
}
126+
127+
/**
128+
* Spring Data Cassandra supports {@code Limit} to reduce the number of returned results.
129+
*/
130+
@Test
131+
void limitResultSize() throws InterruptedException {
132+
133+
assumeThat(CassandraVersion.getReleaseVersion(session).isGreaterThanOrEqualTo(CASSANDRA_3_4)).isTrue();
134+
135+
session.execute("CREATE CUSTOM INDEX ON users (lname) USING 'org.apache.cassandra.index.sasi.SASIIndex';");
136+
/*
137+
Cassandra secondary indexes are created in the background without the possibility to check
138+
whether they are available or not. So we are forced to just wait. *sigh*
139+
*/
140+
Thread.sleep(1000);
141+
142+
LongStream.range(0, 10).forEach(id -> repository.save(new User(id, user.getFirstname(), user.getLastname())));
143+
144+
assertThat(repository.findUsersByLastnameStartsWith("last", Limit.of(5))).hasSize(5);
145+
}
123146
}

‎cassandra/reactive/src/main/java/example/springdata/cassandra/people/ReactivePersonRepository.java

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package example.springdata.cassandra.people;
1717

18+
import org.springframework.data.domain.Limit;
1819
import reactor.core.publisher.Flux;
1920
import reactor.core.publisher.Mono;
2021

@@ -36,6 +37,15 @@ public interface ReactivePersonRepository extends ReactiveCrudRepository<Person,
3637
*/
3738
Flux<Person> findByLastname(String lastname);
3839

40+
/**
41+
* Derived query selecting by {@code lastname} reducing the result size to a given {@link Limit}.
42+
*
43+
* @param lastname
44+
* @param maxResults the maximum number of results returned.
45+
* @return
46+
*/
47+
Flux<Person> findByLastname(String lastname, Limit maxResults);
48+
3949
/**
4050
* String query selecting one entity.
4151
*

‎cassandra/reactive/src/test/java/example/springdata/cassandra/people/ReactivePersonRepositoryIntegrationTest.java

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package example.springdata.cassandra.people;
1717

1818
import example.springdata.cassandra.util.CassandraKeyspace;
19+
import org.springframework.data.domain.Limit;
1920
import reactor.core.publisher.Flux;
2021
import reactor.core.publisher.Mono;
2122
import reactor.test.StepVerifier;
@@ -89,6 +90,14 @@ void shouldQueryDataWithQueryDerivation() {
8990
StepVerifier.create(repository.findByLastname("White")).expectNextCount(2).verifyComplete();
9091
}
9192

93+
/**
94+
* Fetch data limiting result size.
95+
*/
96+
@Test
97+
void limitResultSize() {
98+
StepVerifier.create(repository.findByLastname("White", Limit.of(1))).expectNextCount(1).verifyComplete();
99+
}
100+
92101
/**
93102
* Fetch data using a string query.
94103
*/

‎jpa/example/src/main/java/example/springdata/jpa/simple/SimpleUserRepository.java

+23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.concurrent.CompletableFuture;
2121
import java.util.stream.Stream;
2222

23+
import org.springframework.data.domain.Limit;
2324
import org.springframework.data.domain.Pageable;
2425
import org.springframework.data.domain.Slice;
2526
import org.springframework.data.domain.Sort;
@@ -63,6 +64,17 @@ public interface SimpleUserRepository extends ListCrudRepository<User, Long> {
6364
*/
6465
List<User> findByLastname(String lastname);
6566

67+
/**
68+
* Find at most the number of users defined via maxResults with the given lastname.
69+
* This method will be translated into a query by constructing it directly from the method name as there is no other
70+
* query declared.
71+
*
72+
* @param lastname
73+
* @param maxResults the maximum number of results returned.
74+
* @return
75+
*/
76+
List<User> findByLastname(String lastname, Limit maxResults);
77+
6678
/**
6779
* Returns all users with the given firstname. This method will be translated into a query using the one declared in
6880
* the {@link Query} annotation declared one.
@@ -73,6 +85,17 @@ public interface SimpleUserRepository extends ListCrudRepository<User, Long> {
7385
@Query("select u from User u where u.firstname = :firstname")
7486
List<User> findByFirstname(String firstname);
7587

88+
/**
89+
* Returns at most the number of users defined via {@link Limit} with the given firstname. This method will be
90+
* translated into a query using the one declared in the {@link Query} annotation declared one.
91+
*
92+
* @param firstname
93+
* @param maxResults the maximum number of results returned.
94+
* @return
95+
*/
96+
@Query("select u from User u where u.firstname = :firstname")
97+
List<User> findByFirstname(String firstname, Limit maxResults);
98+
7699
/**
77100
* Returns all users with the given name as first- or lastname. This makes the query to method relation much more
78101
* refactoring-safe as the order of the method parameters is completely irrelevant.

‎jpa/example/src/test/java/example/springdata/jpa/simple/SimpleUserRepositoryTests.java

+18
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.concurrent.CompletableFuture;
2828
import java.util.concurrent.TimeUnit;
2929
import java.util.stream.Collectors;
30+
import java.util.stream.IntStream;
3031
import java.util.stream.Stream;
3132

3233
import org.junit.jupiter.api.Assertions;
@@ -36,6 +37,7 @@
3637
import org.springframework.beans.factory.annotation.Autowired;
3738
import org.springframework.boot.test.context.SpringBootTest;
3839
import org.springframework.dao.InvalidDataAccessApiUsageException;
40+
import org.springframework.data.domain.Limit;
3941
import org.springframework.data.domain.PageRequest;
4042
import org.springframework.data.domain.Sort;
4143
import org.springframework.transaction.annotation.Propagation;
@@ -83,6 +85,22 @@ void findSavedUserByLastname() {
8385
assertThat(repository.findByLastname("lastname")).contains(user);
8486
}
8587

88+
@Test
89+
void findLimitedNumberOfUsersViaDerivedQuery() {
90+
91+
IntStream.range(0, 10).forEach($ -> repository.save(new User(user.getFirstname(), user.getLastname())));
92+
93+
assertThat(repository.findByLastname("lastname", Limit.of(5))).hasSize(5);
94+
}
95+
96+
@Test
97+
void findLimitedNumberOfUsersViaAnnotatedQuery() {
98+
99+
IntStream.range(0, 10).forEach($ -> repository.save(new User(user.getFirstname(), user.getLastname())));
100+
101+
assertThat(repository.findByFirstname(user.getFirstname(), Limit.of(5))).hasSize(5);
102+
}
103+
86104
@Test
87105
void findByFirstnameOrLastname() {
88106

‎mongodb/example/src/main/java/example/springdata/mongodb/customer/CustomerRepository.java

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.List;
1919
import java.util.stream.Stream;
2020

21+
import org.springframework.data.domain.Limit;
2122
import org.springframework.data.domain.Sort;
2223
import org.springframework.data.geo.Distance;
2324
import org.springframework.data.geo.GeoResults;
@@ -41,6 +42,15 @@ public interface CustomerRepository extends CrudRepository<Customer, String> {
4142
*/
4243
List<Customer> findByLastname(String lastname, Sort sort);
4344

45+
/**
46+
* Derived query reducing result size to a given {@link Limit}.
47+
*
48+
* @param lastname
49+
* @param maxResults the maximum number of results returned.
50+
* @return
51+
*/
52+
List<Customer> findByLastname(String lastname, Limit maxResults);
53+
4454
/**
4555
* Showcase for a repository query using geospatial functionality.
4656
*

‎mongodb/example/src/test/java/example/springdata/mongodb/customer/CustomerRepositoryIntegrationTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.springframework.beans.factory.annotation.Autowired;
2929
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
30+
import org.springframework.data.domain.Limit;
3031
import org.springframework.data.geo.Distance;
3132
import org.springframework.data.geo.Metrics;
3233
import org.springframework.data.geo.Point;
@@ -96,6 +97,17 @@ void findCustomersUsingQuerydslSort() {
9697
assertThat(result.get(1)).isEqualTo(oliver);
9798
}
9899

100+
/**
101+
* Test case to show how to reduce result size with dynamic {@link Limit}.
102+
*/
103+
@Test
104+
void limitResultSize() {
105+
106+
var result = repository.findByLastname("Matthews", Limit.of(1));
107+
108+
assertThat(result).hasSize(1);
109+
}
110+
99111
/**
100112
* Test case to show the usage of Java {@link Stream}.
101113
*/

‎mongodb/reactive/src/main/java/example/springdata/mongodb/people/ReactivePersonRepository.java

+14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package example.springdata.mongodb.people;
1717

18+
import java.util.List;
19+
20+
import org.springframework.data.domain.Limit;
1821
import reactor.core.publisher.Flux;
1922
import reactor.core.publisher.Mono;
2023

@@ -37,6 +40,17 @@ public interface ReactivePersonRepository extends ReactiveCrudRepository<Person,
3740
*/
3841
Flux<Person> findByLastname(String lastname);
3942

43+
/**
44+
* Find at most the number of users defined via maxResults with the given lastname.
45+
* This method will be translated into a query by constructing it directly from the method name as there is no other
46+
* query declared.
47+
*
48+
* @param lastname
49+
* @param maxResults the maximum number of results returned.
50+
* @return
51+
*/
52+
Flux<Person> findByLastname(String lastname, Limit maxResults);
53+
4054
/**
4155
* String query selecting one entity.
4256
*

‎mongodb/reactive/src/test/java/example/springdata/mongodb/people/ReactivePersonRepositoryIntegrationTest.java

+9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import example.springdata.mongodb.util.MongoContainers;
21+
import org.springframework.data.domain.Limit;
2122
import reactor.core.publisher.Flux;
2223
import reactor.core.publisher.Mono;
2324
import reactor.test.StepVerifier;
@@ -157,6 +158,14 @@ void shouldQueryDataWithQueryDerivation() {
157158
repository.findByLastname("White").as(StepVerifier::create).expectNextCount(2).verifyComplete();
158159
}
159160

161+
/**
162+
* Limit result size.
163+
*/
164+
@Test
165+
void shouldLimitResultSize() {
166+
repository.findByLastname("White", Limit.of(1)).as(StepVerifier::create).expectNextCount(1).verifyComplete();
167+
}
168+
160169
/**
161170
* Fetch data using a string query.
162171
*/

‎r2dbc/example/src/main/java/example/springdata/r2dbc/basics/CustomerRepository.java

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package example.springdata.r2dbc.basics;
1717

18+
import org.springframework.data.domain.Limit;
1819
import reactor.core.publisher.Flux;
1920

2021
import org.springframework.data.r2dbc.repository.Query;
@@ -28,4 +29,6 @@ interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> {
2829

2930
@Query("select id, firstname, lastname from customer c where c.lastname = :lastname")
3031
Flux<Customer> findByLastname(String lastname);
32+
33+
Flux<Customer> findByLastname(String lastname, Limit limit);
3134
}

‎r2dbc/example/src/test/java/example/springdata/r2dbc/basics/TransactionalServiceIntegrationTests.java

+20
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package example.springdata.r2dbc.basics;
1717

18+
import org.springframework.data.domain.Limit;
1819
import reactor.core.publisher.Hooks;
1920
import reactor.test.StepVerifier;
2021

@@ -72,6 +73,25 @@ void exceptionTriggersRollback() {
7273
.verifyComplete();
7374
}
7475

76+
@Test
77+
void limitResultSize() {
78+
79+
service.save(new Customer(null, "Carter", "Matthews")) //
80+
.as(StepVerifier::create) //
81+
.expectNextMatches(Customer::hasId) //
82+
.verifyComplete();
83+
84+
service.save(new Customer(null, "Evad", "Matthews")) //
85+
.as(StepVerifier::create) //
86+
.expectNextMatches(Customer::hasId) //
87+
.verifyComplete();
88+
89+
repository.findByLastname("Matthews", Limit.of(1)) //
90+
.as(StepVerifier::create) //
91+
.expectNextCount(1)
92+
.verifyComplete();
93+
}
94+
7595
@Test // #500
7696
void insertsDataTransactionally() {
7797

0 commit comments

Comments
 (0)
Please sign in to comment.