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:
-
Imperative
-
Reactive
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:
Keyword | Sample | Logical result |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Repository Delete Queries
The keywords in the preceding table can be used in conjunction with delete…By
to create queries that delete matching documents.
-
Imperative
-
Reactive
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
.
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.
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
:
-
Imperative
-
Reactive
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.
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.
|