Skip to content

Commit

Permalink
Show how to use Limit with repository queries.
Browse files Browse the repository at this point in the history
Add methods taking a Limit parameter to various samples.

Original pull request: #672
Closes #671
  • Loading branch information
christophstrobl authored and mp911de committed Nov 2, 2023
1 parent e90be0c commit f98c7b9
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;

import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.domain.Limit;
import org.springframework.data.repository.CrudRepository;

/**
Expand Down Expand Up @@ -55,4 +56,13 @@ public interface BasicUserRepository extends CrudRepository<User, Long> {
* @return
*/
List<User> findUsersByLastnameStartsWith(String lastnamePrefix);

/**
* Same as {@link #findUsersByLastnameStartsWith(String)} but reducing the result size to a given {@link Limit}.
*
* @param lastnamePrefix
* @param maxResults the maximum number of results returned.
* @return
*/
List<User> findUsersByLastnameStartsWith(String lastnamePrefix, Limit maxResults);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,10 @@ public class User {
public User(Long id) {
this.setId(id);
}

public User(Long id, String firstname, String lastname) {
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assumptions.*;

import java.util.stream.LongStream;

import example.springdata.cassandra.util.CassandraKeyspace;
import example.springdata.cassandra.util.CassandraVersion;

Expand All @@ -26,6 +28,7 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Limit;
import org.springframework.data.util.Version;

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

assertThat(repository.findUsersByLastnameStartsWith("last")).contains(user);
}

/**
* Spring Data Cassandra supports {@code Limit} to reduce the number of returned results.
*/
@Test
void limitResultSize() throws InterruptedException {

assumeThat(CassandraVersion.getReleaseVersion(session).isGreaterThanOrEqualTo(CASSANDRA_3_4)).isTrue();

session.execute("CREATE CUSTOM INDEX ON users (lname) USING 'org.apache.cassandra.index.sasi.SASIIndex';");
/*
Cassandra secondary indexes are created in the background without the possibility to check
whether they are available or not. So we are forced to just wait. *sigh*
*/
Thread.sleep(1000);

LongStream.range(0, 10).forEach(id -> repository.save(new User(id, user.getFirstname(), user.getLastname())));

assertThat(repository.findUsersByLastnameStartsWith("last", Limit.of(5))).hasSize(5);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package example.springdata.cassandra.people;

import org.springframework.data.domain.Limit;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

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

/**
* Derived query selecting by {@code lastname} reducing the result size to a given {@link Limit}.
*
* @param lastname
* @param maxResults the maximum number of results returned.
* @return
*/
Flux<Person> findByLastname(String lastname, Limit maxResults);

/**
* String query selecting one entity.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package example.springdata.cassandra.people;

import example.springdata.cassandra.util.CassandraKeyspace;
import org.springframework.data.domain.Limit;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
Expand Down Expand Up @@ -89,6 +90,14 @@ void shouldQueryDataWithQueryDerivation() {
StepVerifier.create(repository.findByLastname("White")).expectNextCount(2).verifyComplete();
}

/**
* Fetch data limiting result size.
*/
@Test
void limitResultSize() {
StepVerifier.create(repository.findByLastname("White", Limit.of(1))).expectNextCount(1).verifyComplete();
}

/**
* Fetch data using a string query.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;

import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
Expand Down Expand Up @@ -63,6 +64,17 @@ public interface SimpleUserRepository extends ListCrudRepository<User, Long> {
*/
List<User> findByLastname(String lastname);

/**
* Find at most the number of users defined via maxResults with the given lastname.
* This method will be translated into a query by constructing it directly from the method name as there is no other
* query declared.
*
* @param lastname
* @param maxResults the maximum number of results returned.
* @return
*/
List<User> findByLastname(String lastname, Limit maxResults);

/**
* Returns all users with the given firstname. This method will be translated into a query using the one declared in
* the {@link Query} annotation declared one.
Expand All @@ -73,6 +85,17 @@ public interface SimpleUserRepository extends ListCrudRepository<User, Long> {
@Query("select u from User u where u.firstname = :firstname")
List<User> findByFirstname(String firstname);

/**
* Returns at most the number of users defined via {@link Limit} with the given firstname. This method will be
* translated into a query using the one declared in the {@link Query} annotation declared one.
*
* @param firstname
* @param maxResults the maximum number of results returned.
* @return
*/
@Query("select u from User u where u.firstname = :firstname")
List<User> findByFirstname(String firstname, Limit maxResults);

/**
* Returns all users with the given name as first- or lastname. This makes the query to method relation much more
* refactoring-safe as the order of the method parameters is completely irrelevant.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.junit.jupiter.api.Assertions;
Expand All @@ -36,6 +37,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Propagation;
Expand Down Expand Up @@ -83,6 +85,22 @@ void findSavedUserByLastname() {
assertThat(repository.findByLastname("lastname")).contains(user);
}

@Test
void findLimitedNumberOfUsersViaDerivedQuery() {

IntStream.range(0, 10).forEach($ -> repository.save(new User(user.getFirstname(), user.getLastname())));

assertThat(repository.findByLastname("lastname", Limit.of(5))).hasSize(5);
}

@Test
void findLimitedNumberOfUsersViaAnnotatedQuery() {

IntStream.range(0, 10).forEach($ -> repository.save(new User(user.getFirstname(), user.getLastname())));

assertThat(repository.findByFirstname(user.getFirstname(), Limit.of(5))).hasSize(5);
}

@Test
void findByFirstnameOrLastname() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;
import java.util.stream.Stream;

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

/**
* Derived query reducing result size to a given {@link Limit}.
*
* @param lastname
* @param maxResults the maximum number of results returned.
* @return
*/
List<Customer> findByLastname(String lastname, Limit maxResults);

/**
* Showcase for a repository query using geospatial functionality.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.domain.Limit;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
Expand Down Expand Up @@ -96,6 +97,17 @@ void findCustomersUsingQuerydslSort() {
assertThat(result.get(1)).isEqualTo(oliver);
}

/**
* Test case to show how to reduce result size with dynamic {@link Limit}.
*/
@Test
void limitResultSize() {

var result = repository.findByLastname("Matthews", Limit.of(1));

assertThat(result).hasSize(1);
}

/**
* Test case to show the usage of Java {@link Stream}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package example.springdata.mongodb.people;

import java.util.List;

import org.springframework.data.domain.Limit;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

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

/**
* Find at most the number of users defined via maxResults with the given lastname.
* This method will be translated into a query by constructing it directly from the method name as there is no other
* query declared.
*
* @param lastname
* @param maxResults the maximum number of results returned.
* @return
*/
Flux<Person> findByLastname(String lastname, Limit maxResults);

/**
* String query selecting one entity.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.assertj.core.api.Assertions.*;

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

/**
* Limit result size.
*/
@Test
void shouldLimitResultSize() {
repository.findByLastname("White", Limit.of(1)).as(StepVerifier::create).expectNextCount(1).verifyComplete();
}

/**
* Fetch data using a string query.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package example.springdata.r2dbc.basics;

import org.springframework.data.domain.Limit;
import reactor.core.publisher.Flux;

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

@Query("select id, firstname, lastname from customer c where c.lastname = :lastname")
Flux<Customer> findByLastname(String lastname);

Flux<Customer> findByLastname(String lastname, Limit limit);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package example.springdata.r2dbc.basics;

import org.springframework.data.domain.Limit;
import reactor.core.publisher.Hooks;
import reactor.test.StepVerifier;

Expand Down Expand Up @@ -72,6 +73,25 @@ void exceptionTriggersRollback() {
.verifyComplete();
}

@Test
void limitResultSize() {

service.save(new Customer(null, "Carter", "Matthews")) //
.as(StepVerifier::create) //
.expectNextMatches(Customer::hasId) //
.verifyComplete();

service.save(new Customer(null, "Evad", "Matthews")) //
.as(StepVerifier::create) //
.expectNextMatches(Customer::hasId) //
.verifyComplete();

repository.findByLastname("Matthews", Limit.of(1)) //
.as(StepVerifier::create) //
.expectNextCount(1)
.verifyComplete();
}

@Test // #500
void insertsDataTransactionally() {

Expand Down

0 comments on commit f98c7b9

Please sign in to comment.