Cassandra-specific Query Methods

This chapter explains Cassandra-specific query methods. This documentation uses imperative types. By using reactive return types, the same semantics apply to reactive repositories as well.

Most of the data access operations you usually trigger on a repository result in a query being executed against the Apache Cassandra database. Defining such a query is a matter of declaring a method on the repository interface. The following example shows a number of such method declarations:spring-doc.cn

PersonRepository with query methods
interface PersonRepository extends CrudRepository<Person, String> {

    List<Person> findByLastname(String lastname);                           (1)

    Slice<Person> findByFirstname(String firstname, Pageable pageRequest);  (2)

    Window<Person> findByFirstname(String firstname, CassandraScrollPosition pos, Limit limit);  (3)

    List<Person> findByFirstname(String firstname, QueryOptions opts);      (4)

    List<Person> findByFirstname(String firstname, Sort sort);              (5)

    List<Person> findByFirstname(String firstname, Limit limit);            (6)

    Person findByShippingAddress(Address address);                          (7)

    Person findFirstByShippingAddress(Address address);                     (8)

    Stream<Person> findAllBy();                                             (9)

    @AllowFiltering
    List<Person> findAllByAge(int age);                                     (10)
}
1 The method shows a query for all people with the given lastname. The query is derived from parsing the method name for constraints, which can be concatenated with And. Thus, the method name results in a query expression of SELECT * FROM person WHERE lastname = 'lastname'.
2 Applies pagination to a query. You can equip your method signature with a Pageable parameter and let the method return a Slice instance, and we automatically page the query accordingly.
3 Applies scrolling to a query. Scrolling wraps Cassandra’s PagingState into CassandraScrollPosition and allows dynamic limiting. You can also use findTop… for a static limit.
4 Passing a QueryOptions object applies the query options to the resulting query before its execution.
5 Applies dynamic sorting to a query. You can add a Sort parameter to your method signature, and Spring Data automatically applies ordering to the query.
6 Applies dynamic result limiting to a query. Query results can be limited using SELECT … LIMIT.
7 Shows that you can query based on properties that are not a primitive type by using Converter instances registered in CustomConversions. Throws IncorrectResultSizeDataAccessException if more than one match is found.
8 Uses the First keyword to restrict the query to only the first result. Unlike the preceding method, this method does not throw an exception if more than one match is found.
9 Uses a Java 8 Stream to read and convert individual elements while iterating the stream.
10 Shows a query method annotated with @AllowFiltering, to allow server-side filtering.
interface ReactivePersonRepository extends ReactiveSortingRepository<Person, Long> {

  Flux<Person> findByFirstname(String firstname);                                (1)

  Flux<Person> findByFirstname(Publisher<String> firstname);                     (2)

  Mono<Person> findByFirstnameAndLastname(String firstname, String lastname);    (3)

  Mono<Person> findFirstByFirstname(String firstname);                           (4)

  @AllowFiltering
  Flux<Person> findByAge(int age);                                               (5)
}
1 A query for all people with the given firstname. The query is derived by parsing the method name for constraints, which can be concatenated with And and Or. Thus, the method name results in a query expression of SELECT * FROM person WHERE firstname = :firstname.
2 A query for all people with the given firstname once the firstname is emitted from the given Publisher.
3 Find a single entity for the given criteria. Completes with IncorrectResultSizeDataAccessException on non-unique results.
4 Unlike the preceding query, the first entity is always emitted even if the query yields more result rows.
5 A query method annotated with @AllowFiltering, which allows server-side filtering.
Querying non-primary key properties requires secondary indexes.

The following table shows short examples of the keywords that you can use in query methods:spring-doc.cn

Table 1. Supported keywords for query methods
Keyword Sample Logical result

Afterspring-doc.cn

findByBirthdateAfter(Date date)spring-doc.cn

birthdate > datespring-doc.cn

GreaterThanspring-doc.cn

findByAgeGreaterThan(int age)spring-doc.cn

age > agespring-doc.cn

GreaterThanEqualspring-doc.cn

findByAgeGreaterThanEqual(int age)spring-doc.cn

age >= agespring-doc.cn

Beforespring-doc.cn

findByBirthdateBefore(Date date)spring-doc.cn

birthdate < datespring-doc.cn

LessThanspring-doc.cn

findByAgeLessThan(int age)spring-doc.cn

age < agespring-doc.cn

LessThanEqualspring-doc.cn

findByAgeLessThanEqual(int age)spring-doc.cn

age ⇐ agespring-doc.cn

Betweenspring-doc.cn

findByAgeBetween(int from, int to) and findByAgeBetween(Range<Integer> range)spring-doc.cn

age > from AND age < to and lower / upper bounds (> / >= & < / ) according to Rangespring-doc.cn

Inspring-doc.cn

findByAgeIn(Collection ages)spring-doc.cn

age IN (ages…​)spring-doc.cn

Like, StartingWith, EndingWithspring-doc.cn

findByFirstnameLike(String name)spring-doc.cn

firstname LIKE (name as like expression)spring-doc.cn

Containing on Stringspring-doc.cn

findByFirstnameContaining(String name)spring-doc.cn

firstname LIKE (name as like expression)spring-doc.cn

Containing on Collectionspring-doc.cn

findByAddressesContaining(Address address)spring-doc.cn

addresses CONTAINING addressspring-doc.cn

(No keyword)spring-doc.cn

findByFirstname(String name)spring-doc.cn

firstname = namespring-doc.cn

IsTrue, Truespring-doc.cn

findByActiveIsTrue()spring-doc.cn

active = truespring-doc.cn

IsFalse, Falsespring-doc.cn

findByActiveIsFalse()spring-doc.cn

active = falsespring-doc.cn

Repository Delete Queries

The keywords in the preceding table can be used in conjunction with delete…By to create queries that delete matching documents.spring-doc.cn

interface PersonRepository extends Repository<Person, String> {

  void deleteWithoutResultByLastname(String lastname);

  boolean deleteByLastname(String lastname);
}
interface PersonRepository extends Repository<Person, String> {

  Mono<Void> deleteWithoutResultByLastname(String lastname);

  Mono<Boolean> deleteByLastname(String lastname);
}

Delete queries return whether the query was applied or terminate without returning a value using void.spring-doc.cn

Query Options

You can specify query options for query methods by passing a QueryOptions object. The options apply to the query before the actual query execution. QueryOptions is treated as a non-query parameter and is not considered to be a query parameter value. Query options apply to derived and string @Query repository methods.spring-doc.cn

To statically set the consistency level, use the @Consistency annotation on query methods. The declared consistency level is applied to the query each time it is executed. The following example sets the consistency level to ConsistencyLevel.LOCAL_ONE:spring-doc.cn

interface PersonRepository extends CrudRepository<Person, String> {

    @Consistency(ConsistencyLevel.LOCAL_ONE)
    List<Person> findByLastname(String lastname);

    List<Person> findByFirstname(String firstname, QueryOptions options);
}
interface PersonRepository extends ReactiveCrudRepository<Person, String> {

    @Consistency(ConsistencyLevel.LOCAL_ONE)
    Flux<Person> findByLastname(String lastname);

    Flux<Person> findByFirstname(String firstname, QueryOptions options);
}

The DataStax Cassandra documentation includes a good discussion of the available consistency levels.spring-doc.cn

You can control fetch size, consistency level, and retry policy defaults by configuring the following parameters on the CQL API instances: CqlTemplate, AsyncCqlTemplate, and ReactiveCqlTemplate. Defaults apply if the particular query option is not set.