DATACASS-167 - Polishing.
Reformat docs.
This commit is contained in:
@@ -11,9 +11,7 @@ ifdef::backend-epub3[:front-cover-image: image:epub-cover.png[Front Cover,1050,1
|
||||
|
||||
(C) 2008-2020 The original author(s).
|
||||
|
||||
NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not
|
||||
charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed
|
||||
in print or electronically.
|
||||
NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
|
||||
|
||||
include::preface.adoc[]
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
[[preface]]
|
||||
= Preface
|
||||
|
||||
The Spring Data for Apache Cassandra project applies core Spring concepts to the development of solutions using
|
||||
the Cassandra Columnar data store. A "`template`" is provided as a high-level abstraction for storing
|
||||
and querying documents. This project has noticeable similarities to the {spring-framework-docs}data-access.html#jdbc[JDBC support]
|
||||
The Spring Data for Apache Cassandra project applies core Spring concepts to the development of solutions using the Cassandra Columnar data store.
|
||||
A "`template`" is provided as a high-level abstraction for storing and querying documents.
|
||||
This project has noticeable similarities to the {spring-framework-docs}data-access.html#jdbc[JDBC support]
|
||||
in the core Spring Framework.
|
||||
|
||||
This document is the reference guide for Spring Data support for Cassandra. It explains Cassandra module concepts and
|
||||
semantics and the syntax for various stores namespaces.
|
||||
This document is the reference guide for Spring Data support for Cassandra.
|
||||
It explains Cassandra module concepts and semantics and the syntax for various stores namespaces.
|
||||
|
||||
This section provides a basic introduction to Spring, Spring Data, and the Cassandra database. The rest of the document
|
||||
refers only to Spring Data for Apache Cassandra features and assumes you are familiar with Cassandra as well as
|
||||
core Spring concepts.
|
||||
This section provides a basic introduction to Spring, Spring Data, and the Cassandra database.
|
||||
The rest of the document refers only to Spring Data for Apache Cassandra features and assumes you are familiar with Cassandra as well as core Spring concepts.
|
||||
|
||||
[[get-started:first-steps:spring]]
|
||||
== Knowing Spring
|
||||
@@ -27,35 +26,33 @@ functionality, including:
|
||||
* {spring-framework-docs}data-access.html[DAO support]
|
||||
* {spring-framework-docs}data-access.html#dao-exceptions[DAO Exception Hierarchy]
|
||||
|
||||
While it is not important to know the Spring APIs, understanding the concepts behind them is important. At a minimum, the idea
|
||||
behind IoC should be familiar, no matter what IoC container you choose to use.
|
||||
While it is not important to know the Spring APIs, understanding the concepts behind them is important.
|
||||
At a minimum, the idea behind IoC should be familiar, no matter what IoC container you choose to use.
|
||||
|
||||
The core functionality of the Cassandra support can be used directly, with no need to invoke the IoC services
|
||||
of the Spring container. This is much like `JdbcTemplate`, which can be used 'standalone' without any other services
|
||||
of the Spring container. To use all the features of Spring Data for Apache Cassandra, such as the repository support,
|
||||
you must configure some parts of the library by using Spring.
|
||||
The core functionality of the Cassandra support can be used directly, with no need to invoke the IoC services of the Spring container.
|
||||
This is much like `JdbcTemplate`, which can be used 'standalone' without any other services of the Spring container.
|
||||
To use all the features of Spring Data for Apache Cassandra, such as the repository support, you must configure some parts of the library by using Spring.
|
||||
|
||||
To learn more about Spring, you can refer to the comprehensive {spring-framework-docs}[documentation]
|
||||
that explains the Spring Framework in detail. There are a lot of articles, blog entries, and books on Spring.
|
||||
that explains the Spring Framework in detail.
|
||||
There are a lot of articles, blog entries, and books on Spring.
|
||||
See the Spring Framework https://projects.spring.io/spring-framework/[home page] for more information.
|
||||
|
||||
[[get-started:first-steps:nosql]]
|
||||
== Knowing NoSQL and Cassandra
|
||||
|
||||
NoSQL stores have taken the storage world by storm. It is a vast domain with a plethora of solutions, terms, and patterns.
|
||||
(To make things worse, even the term itself has multiple https://www.google.com/search?q=nosoql+acronym[meanings].)
|
||||
While some of the principles are common, it is crucial that you be familiar to some degree with
|
||||
the Cassandra Columnar NoSQL Datastore supported by Spring Data for Apache Cassandra. The best way to get acquainted with Cassandra
|
||||
is to read the documentation and follow the examples. It usually does not take more then 5-10 minutes to go through them,
|
||||
and, if you come from a RDBMS background, these exercises can often be an eye opener.
|
||||
NoSQL stores have taken the storage world by storm.
|
||||
It is a vast domain with a plethora of solutions, terms, and patterns.
|
||||
(To make things worse, even the term itself has multiple https://www.google.com/search?q=nosoql+acronym[meanings].) While some of the principles are common, it is crucial that you be familiar to some degree with the Cassandra Columnar NoSQL Datastore supported by Spring Data for Apache Cassandra.
|
||||
The best way to get acquainted with Cassandra is to read the documentation and follow the examples.
|
||||
It usually does not take more then 5-10 minutes to go through them, and, if you come from a RDBMS background, these exercises can often be an eye opener.
|
||||
|
||||
The starting point for learning about Cassandra is https://cassandra.apache.org/[cassandra.apache.org]. Also, here is
|
||||
a list of other useful resources:
|
||||
The starting point for learning about Cassandra is https://cassandra.apache.org/[cassandra.apache.org].
|
||||
Also, here is a list of other useful resources:
|
||||
|
||||
* The https://datastax.com/[DataStax] site offers https://www.datastax.com/what-we-offer/products-services/support[commercial support]
|
||||
and many resources, including, but not limited to, https://docs.datastax.com/en/landing_page/doc/landing_page/current.html[documentation],
|
||||
https://docs.datastax.com/en/landing_page/doc/landing_page/current.html[DataStax Academy], a https://www.datastax.com/dev/blog[Tech Blog],
|
||||
and so on.
|
||||
https://docs.datastax.com/en/landing_page/doc/landing_page/current.html[DataStax Academy], a https://www.datastax.com/dev/blog[Tech Blog], and so on.
|
||||
* The https://academy.datastax.com/resources/ds101-introduction-cassandra[DataStax Academy introduction to Cassandra].
|
||||
* The https://cassandra.apache.org/doc/latest/getting_started/index.html[Cassandra Quick Start Guide].
|
||||
|
||||
@@ -68,16 +65,15 @@ It requires https://cassandra.apache.org/[Cassandra] 2.0 or later.
|
||||
|
||||
== Additional Help Resources
|
||||
|
||||
Learning a new framework is not always straight forward. In this section, we try to provide what we
|
||||
think is an easy-to-follow guide for starting with the Spring Data for Apache Cassandra module.
|
||||
Learning a new framework is not always straight forward.
|
||||
In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data for Apache Cassandra module.
|
||||
However, if you encounter issues or you need advice, feel free to use one of the links below:
|
||||
|
||||
[[get-started:help:community]]
|
||||
Community Forum::
|
||||
Spring Data on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a
|
||||
tag for all Spring Data (not just Cassandra) users to share information and help each other.
|
||||
Note that registration is needed only for posting. The two key tags to search for related answers to
|
||||
this project are https://stackoverflow.com/questions/tagged/spring-data[spring-data] and https://stackoverflow.com/questions/tagged/spring-data-cassandra[spring-data-cassandra].
|
||||
Spring Data on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a tag for all Spring Data (not just Cassandra) users to share information and help each other.
|
||||
Note that registration is needed only for posting.
|
||||
The two key tags to search for related answers to this project are https://stackoverflow.com/questions/tagged/spring-data[spring-data] and https://stackoverflow.com/questions/tagged/spring-data-cassandra[spring-data-cassandra].
|
||||
|
||||
[[get-started:help:professional]]
|
||||
Professional Support::
|
||||
@@ -87,17 +83,14 @@ https://pivotal.io/[Pivotal Sofware, Inc.], the company behind Spring Data and S
|
||||
[[get-started:up-to-date]]
|
||||
=== Following Development
|
||||
|
||||
For information on the Spring Data for Apache Cassandra source code repository, nightly builds, and snapshot artifacts
|
||||
see the https://projects.spring.io/spring-data-cassandra/[Spring Data for Apache Cassandra home page].
|
||||
You can help make Spring Data best serve the needs of the Spring community by interacting with developers
|
||||
through the community on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow].
|
||||
For information on the Spring Data for Apache Cassandra source code repository, nightly builds, and snapshot artifacts see the https://projects.spring.io/spring-data-cassandra/[Spring Data for Apache Cassandra home page].
|
||||
You can help make Spring Data best serve the needs of the Spring community by interacting with developers through the community on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow].
|
||||
To follow developer activity, look for the mailing list information on the Spring Data for Apache Cassandra home page.
|
||||
If you encounter a bug or want to suggest an improvement, please create a ticket on the Spring Data issue
|
||||
https://jira.spring.io/browse/DATACASS[tracker]. To stay up-to-date with the latest news and announcements
|
||||
in the Spring ecosystem, subscribe to the Spring Community https://spring.io[Portal].
|
||||
https://jira.spring.io/browse/DATACASS[tracker].
|
||||
To stay up-to-date with the latest news and announcements in the Spring ecosystem, subscribe to the Spring Community https://spring.io[Portal].
|
||||
Finally, you can follow the Spring https://spring.io/blog[blog] or the project team on Twitter (https://twitter.com/SpringData[SpringData]).
|
||||
|
||||
|
||||
[[get-started:project-metadata]]
|
||||
=== Project Metadata
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Spring Data for Apache Cassandra uses the `EntityCallback` API for its auditing
|
||||
| Reactive/BeforeSaveCallback
|
||||
| `onBeforeSave(T entity, CqlIdentifier tableName, Statement statement)`
|
||||
| Invoked before a domain object is saved. +
|
||||
Can modify the target, to be persisted, `com.datastax.driver.core.Statement` containing all mapped entity information.
|
||||
Can modify the target, to be persisted, `com.datastax.driver.core.Statement` containing all mapped entity information.
|
||||
| `Ordered.LOWEST_PRECEDENCE`
|
||||
|
||||
|===
|
||||
|
||||
@@ -8,8 +8,8 @@ You should understand the basic concepts explained there before proceeding.
|
||||
[[cassandra-repo-usage]]
|
||||
== Usage
|
||||
|
||||
To access domain entities stored in Apache Cassandra, you can use Spring Data's sophisticated repository support,
|
||||
which significantly eases implementing DAOs. To do so, create an interface for your repository, as the following example shows:
|
||||
To access domain entities stored in Apache Cassandra, you can use Spring Data's sophisticated repository support, which significantly eases implementing DAOs.
|
||||
To do so, create an interface for your repository, as the following example shows:
|
||||
|
||||
.Sample Person entity
|
||||
====
|
||||
@@ -29,8 +29,7 @@ public class Person {
|
||||
====
|
||||
|
||||
Note that the entity has a property named `id` of type `String`.
|
||||
The default serialization mechanism used in `CassandraTemplate` (which backs the repository support)
|
||||
regards properties named `id` as being the row ID.
|
||||
The default serialization mechanism used in `CassandraTemplate` (which backs the repository support) regards properties named `id` as being the row ID.
|
||||
|
||||
The following example shows a repository definition to persist `Person` entities:
|
||||
|
||||
@@ -49,9 +48,9 @@ Right now, the interface in the preceding example serves only typing purposes, b
|
||||
|
||||
Next, in your Spring configuration, add the following (if you use Java for configuration):
|
||||
|
||||
If you want to use Java configuration, use the `@EnableCassandraRepositories` annotation. The annotation carries
|
||||
the same attributes as the namespace element. If no base package is configured, the infrastructure scans
|
||||
the package of the annotated configuration class.
|
||||
If you want to use Java configuration, use the `@EnableCassandraRepositories` annotation.
|
||||
The annotation carries the same attributes as the namespace element.
|
||||
If no base package is configured, the infrastructure scans the package of the annotated configuration class.
|
||||
The following example shows how to use the `@EnableCassandraRepositories` annotation:
|
||||
|
||||
.Java configuration for repositories
|
||||
@@ -105,16 +104,12 @@ If you want to use XML configuration, then the following example shows a minimal
|
||||
----
|
||||
====
|
||||
|
||||
The `cassandra:repositories` namespace element causes the base packages to be scanned for interfaces that
|
||||
extend `CrudRepository` and create Spring beans for each one found. By default, the repositories are
|
||||
wired with a `CassandraTemplate` Spring bean called `cassandraTemplate`, so you only need to configure
|
||||
The `cassandra:repositories` namespace element causes the base packages to be scanned for interfaces that extend `CrudRepository` and create Spring beans for each one found.
|
||||
By default, the repositories are wired with a `CassandraTemplate` Spring bean called `cassandraTemplate`, so you only need to configure
|
||||
`cassandra-template-ref` explicitly if you deviate from this convention.
|
||||
|
||||
|
||||
|
||||
Because our domain repository extends `CrudRepository`, it provides you with basic CRUD operations.
|
||||
Working with the repository instance is a matter of injecting the repository as a dependency into a client,
|
||||
as the following example does by autowiring `PersonRepository`:
|
||||
Working with the repository instance is a matter of injecting the repository as a dependency into a client, as the following example does by autowiring `PersonRepository`:
|
||||
|
||||
.Basic access to Person entities
|
||||
====
|
||||
@@ -136,7 +131,10 @@ public class PersonRepositoryTests {
|
||||
----
|
||||
====
|
||||
|
||||
Cassandra repositories support paging and sorting for paginated and sorted access to the entities. Cassandra paging requires a paging state to forward-only navigate through pages. A `Slice` keeps track of the current paging state and allows for creation of a `Pageable` to request the next page. The following example shows how to set up paging access to `Person` entities:
|
||||
Cassandra repositories support paging and sorting for paginated and sorted access to the entities.
|
||||
Cassandra paging requires a paging state to forward-only navigate through pages.
|
||||
A `Slice` keeps track of the current paging state and allows for creation of a `Pageable` to request the next page.
|
||||
The following example shows how to set up paging access to `Person` entities:
|
||||
|
||||
.Paging access to `Person` entities
|
||||
====
|
||||
@@ -165,15 +163,15 @@ public class PersonRepositoryTests {
|
||||
|
||||
NOTE: Cassandra repositories do not extend `PagingAndSortingRepository`, because classic paging patterns using limit/offset are not applicable to Cassandra.
|
||||
|
||||
The preceding example creates an application context with Spring's unit test support, which performs annotation-based
|
||||
dependency injection into the test class. Inside the test cases (the test methods), we use the repository to query
|
||||
the data store. We invoke the repository query method that requests all `Person` instances.
|
||||
The preceding example creates an application context with Spring's unit test support, which performs annotation-based dependency injection into the test class.
|
||||
Inside the test cases (the test methods), we use the repository to query the data store.
|
||||
We invoke the repository query method that requests all `Person` instances.
|
||||
|
||||
[[cassandra.repositories.queries]]
|
||||
== Query Methods
|
||||
|
||||
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.
|
||||
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:
|
||||
|
||||
.PersonRepository with query methods
|
||||
@@ -200,17 +198,18 @@ public interface PersonRepository extends CrudRepository<Person, String> {
|
||||
List<Person> findAllByAge(int age); <8>
|
||||
}
|
||||
----
|
||||
<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.
|
||||
<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> Passing a `QueryOptions` object applies the query options to the resulting query before its execution.
|
||||
<4> 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.
|
||||
<5> 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.
|
||||
<6> 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.
|
||||
<4> 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.
|
||||
<5> 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.
|
||||
<6> 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.
|
||||
<7> Uses a Java 8 `Stream` to read and convert individual elements while iterating the stream.
|
||||
<8> Shows a query method annotated with `@AllowFiltering`, to allow server-side filtering.
|
||||
====
|
||||
@@ -219,7 +218,7 @@ NOTE: Querying non-primary key properties requires secondary indexes.
|
||||
|
||||
The following table shows short examples of the keywords that you can use in query methods:
|
||||
|
||||
[cols="1,2,3", options="header"]
|
||||
[cols="1,2,3",options="header"]
|
||||
.Supported keywords for query methods
|
||||
|===
|
||||
| Keyword
|
||||
@@ -333,18 +332,16 @@ public interface PersonRepository extends CrudRepository<Person, String> {
|
||||
|
||||
The DataStax Cassandra documentation includes https://docs.datastax.com/en/cassandra/3.0/cassandra/dml/dmlConfigConsistency.html[a good discussion of the available consistency levels].
|
||||
|
||||
NOTE: 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.
|
||||
NOTE: 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.
|
||||
|
||||
[[cassandra.repositories.misc.cdi-integration]]
|
||||
=== CDI Integration
|
||||
|
||||
Instances of the repository interfaces are usually created by a container, and the Spring container is
|
||||
the most natural choice when working with Spring Data. Spring Data for Apache Cassandra ships with
|
||||
a custom CDI extension that allows using the repository abstraction in CDI environments. The extension
|
||||
is part of the JAR. To activate it, drop the Spring Data for Apache Cassandra JAR
|
||||
into your classpath. You can now set up the infrastructure by implementing a CDI Producer for the
|
||||
Instances of the repository interfaces are usually created by a container, and the Spring container is the most natural choice when working with Spring Data.
|
||||
Spring Data for Apache Cassandra ships with a custom CDI extension that allows using the repository abstraction in CDI environments.
|
||||
The extension is part of the JAR. To activate it, drop the Spring Data for Apache Cassandra JAR into your classpath.
|
||||
You can now set up the infrastructure by implementing a CDI Producer for the
|
||||
`CassandraTemplate`, as the following examlpe shows:
|
||||
|
||||
====
|
||||
@@ -354,10 +351,8 @@ include::../{example-root}/CassandraTemplateProducer.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
The Spring Data for Apache Cassandra CDI extension picks up `CassandraOperations` as a CDI bean
|
||||
and creates a proxy for a Spring Data repository whenever a bean of a repository type is requested by the container.
|
||||
Thus, obtaining an instance of a Spring Data repository is a matter of declaring an injected property,
|
||||
as the following example shows:
|
||||
The Spring Data for Apache Cassandra CDI extension picks up `CassandraOperations` as a CDI bean and creates a proxy for a Spring Data repository whenever a bean of a repository type is requested by the container.
|
||||
Thus, obtaining an instance of a Spring Data repository is a matter of declaring an injected property, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
|
||||
@@ -12,25 +12,23 @@ Spring Data support for Apache Cassandra contains a wide range of features:
|
||||
* Java-based query, criteria, and update DSLs.
|
||||
* Automatic implementation of `Repository` interfaces including support for custom finder methods.
|
||||
|
||||
For most data-oriented tasks, you can use the `CassandraTemplate` or the `Repository` support, both of which use the
|
||||
rich object-mapping functionality. `CqlTemplate` is commonly used to increment counters or perform ad-hoc CRUD
|
||||
operations. `CqlTemplate` also provides callback methods that make it easy to get low-level API objects,
|
||||
such as `com.datastax.oss.driver.api.core.CqlSession`, which lets you communicate directly with Cassandra.
|
||||
Spring Data for Apache Cassandra uses consistent naming conventions on objects in various APIs to those found in
|
||||
the DataStax Java Driver so that they are familiar and so that you can map your existing knowledge onto the Spring APIs.
|
||||
For most data-oriented tasks, you can use the `CassandraTemplate` or the `Repository` support, both of which use the rich object-mapping functionality. `CqlTemplate` is commonly used to increment counters or perform ad-hoc CRUD operations. `CqlTemplate` also provides callback methods that make it easy to get low-level API objects, such as `com.datastax.oss.driver.api.core.CqlSession`, which lets you communicate directly with Cassandra.
|
||||
Spring Data for Apache Cassandra uses consistent naming conventions on objects in various APIs to those found in the DataStax Java Driver so that they are familiar and so that you can map your existing knowledge onto the Spring APIs.
|
||||
|
||||
[[cassandra.getting-started]]
|
||||
== Getting Started
|
||||
|
||||
Spring Data for Apache Cassandra requires Apache Cassandra 2.1 or later and Datastax Java Driver 4.0 or later. An easy way to quickly set up and bootstrap a working environment is to create a Spring-based project in https://spring.io/tools/sts[STS] or use https://start.spring.io/[Spring Initializer].
|
||||
Spring Data for Apache Cassandra requires Apache Cassandra 2.1 or later and Datastax Java Driver 4.0 or later.
|
||||
An easy way to quickly set up and bootstrap a working environment is to create a Spring-based project in https://spring.io/tools/sts[STS] or use https://start.spring.io/[Spring Initializer].
|
||||
|
||||
First, you need to set up a running Apache Cassandra server. See the
|
||||
First, you need to set up a running Apache Cassandra server.
|
||||
See the
|
||||
https://cassandra.apache.org/doc/latest/getting_started/index.html[Apache Cassandra Quick Start Guide]
|
||||
for an explanation on how to start Apache Cassandra. Once installed, starting Cassandra is typically a matter of
|
||||
executing the following command: `CASSANDRA_HOME/bin/cassandra -f`.
|
||||
for an explanation on how to start Apache Cassandra.
|
||||
Once installed, starting Cassandra is typically a matter of executing the following command: `CASSANDRA_HOME/bin/cassandra -f`.
|
||||
|
||||
To create a Spring project in STS, go to File -> New -> Spring Template Project -> Simple Spring Utility Project
|
||||
and press Yes when prompted. Then enter a project and a package name, such as `org.spring.data.cassandra.example`.
|
||||
To create a Spring project in STS, go to File -> New -> Spring Template Project -> Simple Spring Utility Project and press Yes when prompted.
|
||||
Then enter a project and a package name, such as `org.spring.data.cassandra.example`.
|
||||
|
||||
Then you can add the following dependency declaration to your pom.xml file's `dependencies` section.
|
||||
|
||||
@@ -58,8 +56,7 @@ Also, you should change the version of Spring in the pom.xml file to be as follo
|
||||
----
|
||||
====
|
||||
|
||||
If using a milestone release instead of a GA release, you also need to add the location of the Spring Milestone
|
||||
repository for Maven to your pom.xml file so that it is at the same level of your `<dependencies/>` element, as follows:
|
||||
If using a milestone release instead of a GA release, you also need to add the location of the Spring Milestone repository for Maven to your pom.xml file so that it is at the same level of your `<dependencies/>` element, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -108,17 +105,16 @@ Optionally, you can override these mapping names to match your Cassandra databas
|
||||
|
||||
To get a feel for how the library works, you can download and play around with
|
||||
https://github.com/spring-projects/spring-data-examples[several examples].
|
||||
.
|
||||
.
|
||||
|
||||
[[cassandra.connectors]]
|
||||
== Connecting to Cassandra with Spring
|
||||
|
||||
One of the first tasks when using Apache Cassandra with Spring is to create a `com.datastax.oss.driver.api.core.CqlSession` object by
|
||||
using the Spring IoC container. You can do so either by using Java-based bean metadata or by using XML-based
|
||||
bean metadata. These are discussed in the following sections.
|
||||
One of the first tasks when using Apache Cassandra with Spring is to create a `com.datastax.oss.driver.api.core.CqlSession` object by using the Spring IoC container.
|
||||
You can do so either by using Java-based bean metadata or by using XML-based bean metadata.
|
||||
These are discussed in the following sections.
|
||||
|
||||
NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of
|
||||
XML-based metadata, see the high-level introduction in the reference docs
|
||||
NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs
|
||||
https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.0.html#new-java-configuration[here]
|
||||
as well as the detailed documentation {spring-framework-docs}core.html#beans-java-instantiating-container[here].
|
||||
|
||||
@@ -137,11 +133,9 @@ include::../{example-root}/AppConfig.java[tags=class]
|
||||
|
||||
This approach lets you use the standard `com.datastax.oss.driver.api.core.CqlSession` API that you may already know.
|
||||
|
||||
An alternative is to register an instance of `com.datastax.oss.driver.api.core.CqlSession` with the container by
|
||||
using Spring's `CqlSessionFactoryBean`. As compared to instantiating
|
||||
a `com.datastax.oss.driver.api.core.CqlSession` instance directly, the `FactoryBean` approach has the added advantage of also
|
||||
providing the container with an `ExceptionTranslator` implementation that translates Cassandra exceptions to exceptions
|
||||
in Spring's portable `DataAccessException` hierarchy. This hierarchy and the use of
|
||||
An alternative is to register an instance of `com.datastax.oss.driver.api.core.CqlSession` with the container by using Spring's `CqlSessionFactoryBean`.
|
||||
As compared to instantiating a `com.datastax.oss.driver.api.core.CqlSession` instance directly, the `FactoryBean` approach has the added advantage of also providing the container with an `ExceptionTranslator` implementation that translates Cassandra exceptions to exceptions in Spring's portable `DataAccessException` hierarchy.
|
||||
This hierarchy and the use of
|
||||
`@Repository` is described in {spring-framework-docs}data-access.html[Spring's DAO support features].
|
||||
|
||||
The following example shows Java-based factory class usage:
|
||||
@@ -167,14 +161,13 @@ include::../{example-root}/CassandraConfig.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
Creating configuration classes that register Spring Data for Apache Cassandra components can be an exhausting challenge,
|
||||
so Spring Data for Apache Cassandra comes with a pre-built configuration support class. Classes that extend from
|
||||
Creating configuration classes that register Spring Data for Apache Cassandra components can be an exhausting challenge, so Spring Data for Apache Cassandra comes with a pre-built configuration support class.
|
||||
Classes that extend from
|
||||
`AbstractCassandraConfiguration` register beans for Spring Data for Apache Cassandra use.
|
||||
`AbstractCassandraConfiguration` lets you provide various configuration options, such as initial entities,
|
||||
default query options, pooling options, socket options, and many more. `AbstractCassandraConfiguration` also supports
|
||||
you with schema generation based on initial entities, if any are provided. Extending from
|
||||
`AbstractCassandraConfiguration` requires you to at least provide the keyspace name by implementing
|
||||
the `getKeyspaceName` method. The following example shows how to register beans by using `AbstractCassandraConfiguration`:
|
||||
`AbstractCassandraConfiguration` lets you provide various configuration options, such as initial entities, default query options, pooling options, socket options, and many more. `AbstractCassandraConfiguration` also supports you with schema generation based on initial entities, if any are provided.
|
||||
Extending from
|
||||
`AbstractCassandraConfiguration` requires you to at least provide the keyspace name by implementing the `getKeyspaceName` method.
|
||||
The following example shows how to register beans by using `AbstractCassandraConfiguration`:
|
||||
|
||||
.Registering Spring Data for Apache Cassandra beans by using `AbstractCassandraConfiguration`
|
||||
====
|
||||
@@ -192,7 +185,8 @@ This section describes how to configure Spring Data Cassandra with XML.
|
||||
[[cassandra-connectors.xmlconfig.ext_properties]]
|
||||
==== Externalizing Connection Properties
|
||||
|
||||
To externalize connection properties, you should first create a properties file that contains the information needed to connect to Cassandra. `contactpoints` and `keyspace` are the equired fields. We added `port` for clarity.
|
||||
To externalize connection properties, you should first create a properties file that contains the information needed to connect to Cassandra. `contactpoints` and `keyspace` are the equired fields.
|
||||
We added `port` for clarity.
|
||||
|
||||
The following example shows our properties file, called `cassandra.properties`:
|
||||
|
||||
@@ -243,15 +237,14 @@ The following example shows how to configure the `cassandra` namespace:
|
||||
----
|
||||
====
|
||||
|
||||
The XML configuration elements for more advanced Cassandra configuration are shown below. These elements all use
|
||||
default bean names to keep the configuration code clean and readable.
|
||||
The XML configuration elements for more advanced Cassandra configuration are shown below.
|
||||
These elements all use default bean names to keep the configuration code clean and readable.
|
||||
|
||||
While the preceding example shows how easy it is to configure Spring to connect to Cassandra, there are many other options.
|
||||
Basically, any option available with the DataStax Java Driver is also available in the Spring Data for Apache Cassandra
|
||||
configuration. This includes but is not limited to authentication, load-balancing policies, retry policies,
|
||||
and pooling options. All of the Spring Data for Apache Cassandra method names and XML elements are named exactly
|
||||
(or as close as possible) like the configuration options on the driver so that mapping any existing driver configuration
|
||||
should be straight forward. The following example shows how to configure Spring Data components by using XML
|
||||
Basically, any option available with the DataStax Java Driver is also available in the Spring Data for Apache Cassandra configuration.
|
||||
This includes but is not limited to authentication, load-balancing policies, retry policies, and pooling options.
|
||||
All of the Spring Data for Apache Cassandra method names and XML elements are named exactly (or as close as possible) like the configuration options on the driver so that mapping any existing driver configuration should be straight forward.
|
||||
The following example shows how to configure Spring Data components by using XML
|
||||
|
||||
.Configuring Spring Data components by using XML
|
||||
====
|
||||
@@ -293,12 +286,13 @@ Spring Data for Apache Cassandra can support you with schema creation.
|
||||
|
||||
=== Keyspaces and Lifecycle Scripts
|
||||
|
||||
The first thing to start with is a Cassandra keyspace. A keyspace is a logical grouping of tables that share
|
||||
the same replication factor and replication strategy. Keyspace management is located in the `CqlSession` configuration,
|
||||
which has the `KeyspaceSpecification` and startup and shutdown CQL script execution.
|
||||
The first thing to start with is a Cassandra keyspace.
|
||||
A keyspace is a logical grouping of tables that share the same replication factor and replication strategy.
|
||||
Keyspace management is located in the `CqlSession` configuration, which has the `KeyspaceSpecification` and startup and shutdown CQL script execution.
|
||||
|
||||
Declaring a keyspace with a specification allows creating and dropping of the Keyspace. It derives CQL from
|
||||
the specification so that you need not write CQL yourself. The following example specifies a Cassadra keyspace by using XML:
|
||||
Declaring a keyspace with a specification allows creating and dropping of the Keyspace.
|
||||
It derives CQL from the specification so that you need not write CQL yourself.
|
||||
The following example specifies a Cassadra keyspace by using XML:
|
||||
|
||||
.Specifying a Cassandra keyspace by using XML
|
||||
====
|
||||
@@ -327,10 +321,9 @@ include::../{example-root}/CreateKeyspaceConfiguration.java[tags=class]
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: Keyspace creation allows rapid bootstrapping without the need of external keyspace management. This can be useful
|
||||
for certain scenarios but should be used with care. Dropping a keyspace on application shutdown removes the keyspace
|
||||
and all data from the tables in the keyspace.
|
||||
|
||||
NOTE: Keyspace creation allows rapid bootstrapping without the need of external keyspace management.
|
||||
This can be useful for certain scenarios but should be used with care.
|
||||
Dropping a keyspace on application shutdown removes the keyspace and all data from the tables in the keyspace.
|
||||
|
||||
[[cassandra.schema-management.initializing]]
|
||||
=== Initializing a `SessionFactory`
|
||||
@@ -440,12 +433,10 @@ If you need more control than you get from the XML namespace, you can use the `S
|
||||
[[cassandra.schema-management.initializing.component]]
|
||||
===== Initialization of Other Components that Depend on the Keyspace
|
||||
|
||||
A large class of applications (those that do not use the database until after the Spring context has started) can use the database initializer with no further
|
||||
complications.
|
||||
A large class of applications (those that do not use the database until after the Spring context has started) can use the database initializer with no further complications.
|
||||
If your application is not one of those, you might need to read the rest of this section.
|
||||
|
||||
The database initializer depends on a `SessionFactory` instance and runs the scripts provided in its initialization callback (analogous to an `init-method` in an XML bean
|
||||
definition, a `@PostConstruct` method in a component, or the `afterPropertiesSet()` method in a component that implements `InitializingBean`).
|
||||
The database initializer depends on a `SessionFactory` instance and runs the scripts provided in its initialization callback (analogous to an `init-method` in an XML bean definition, a `@PostConstruct` method in a component, or the `afterPropertiesSet()` method in a component that implements `InitializingBean`).
|
||||
If other beans depend on the same data source and use the session factory in an initialization callback, there might be a problem because the data has not yet been initialized.
|
||||
A common example of this is a cache that initializes eagerly and loads data from the database on application startup.
|
||||
|
||||
@@ -474,12 +465,17 @@ This structure is common in Spring web applications but can be more generally ap
|
||||
Spring Data for Apache Cassandra approaches data access with mapped entity classes that fit your data model.
|
||||
You can use these entity classes to create Cassandra table specifications and user type definitions.
|
||||
|
||||
Schema creation is tied to `CqlSession` initialization by `SchemaAction`. The following actions are supported:
|
||||
Schema creation is tied to `CqlSession` initialization by `SchemaAction`.
|
||||
The following actions are supported:
|
||||
|
||||
* `SchemaAction.NONE`: No tables or types are created or dropped. This is the default setting.
|
||||
* `SchemaAction.CREATE`: Create tables, indexes, and user-defined types from entities annotated with `@Table` and types annotated with `@UserDefinedType`. Existing tables or types cause an error if you tried to create the type.
|
||||
* `SchemaAction.CREATE_IF_NOT_EXISTS`: Like `SchemaAction.CREATE` but with `IF NOT EXISTS` applied. Existing tables or types do not cause any errors but may remain stale.
|
||||
* `SchemaAction.RECREATE`: Drops and recreates existing tables and types that are known to be used. Tables and types that are not configured in the application are not dropped.
|
||||
* `SchemaAction.NONE`: No tables or types are created or dropped.
|
||||
This is the default setting.
|
||||
* `SchemaAction.CREATE`: Create tables, indexes, and user-defined types from entities annotated with `@Table` and types annotated with `@UserDefinedType`.
|
||||
Existing tables or types cause an error if you tried to create the type.
|
||||
* `SchemaAction.CREATE_IF_NOT_EXISTS`: Like `SchemaAction.CREATE` but with `IF NOT EXISTS` applied.
|
||||
Existing tables or types do not cause any errors but may remain stale.
|
||||
* `SchemaAction.RECREATE`: Drops and recreates existing tables and types that are known to be used.
|
||||
Tables and types that are not configured in the application are not dropped.
|
||||
* `SchemaAction.RECREATE_DROP_UNUSED`: Drops all tables and types and recreates only known tables and types.
|
||||
|
||||
NOTE: `SchemaAction.RECREATE` and `SchemaAction.RECREATE_DROP_UNUSED` drop your tables and lose all data.
|
||||
@@ -487,11 +483,12 @@ NOTE: `SchemaAction.RECREATE` and `SchemaAction.RECREATE_DROP_UNUSED` drop your
|
||||
|
||||
==== Enabling Tables and User-Defined Types for Schema Management
|
||||
|
||||
<<mapping.usage>> explains object mapping with conventions and annotations. To prevent
|
||||
unwanted classes from being created as a table or a type, schema management is only active
|
||||
for entities annotated with `@Table` and user-defined types annotated with `@UserDefinedType`. Entities are discovered by scanning the classpath.
|
||||
Entity scanning requires one or more base packages. Tuple-typed columns that use `TupleValue` do not provide
|
||||
any typing details. Consequently, you must annotate such column properties with `@CassandraType(type = TUPLE, typeArguments = …)`
|
||||
<<mapping.usage>> explains object mapping with conventions and annotations.
|
||||
To prevent unwanted classes from being created as a table or a type, schema management is only active for entities annotated with `@Table` and user-defined types annotated with `@UserDefinedType`.
|
||||
Entities are discovered by scanning the classpath.
|
||||
Entity scanning requires one or more base packages.
|
||||
Tuple-typed columns that use `TupleValue` do not provide any typing details.
|
||||
Consequently, you must annotate such column properties with `@CassandraType(type = TUPLE, typeArguments = …)`
|
||||
to specify the desired column type.
|
||||
|
||||
The following example shows how to specify entity base packages in XML configuration:
|
||||
@@ -519,38 +516,34 @@ include::../{example-root}/EntityBasePackagesConfiguration.java[tags=class]
|
||||
[[cassandra.cql-template]]
|
||||
== `CqlTemplate`
|
||||
|
||||
The `CqlTemplate` class is the central class in the core CQL package. It handles the creation and release of resources.
|
||||
It performs the basic tasks of the core CQL workflow, such as statement creation and execution, and leaves application code
|
||||
to provide CQL and extract results. The `CqlTemplate` class executes CQL queries and update statements, performs
|
||||
iteration over `ResultSet` instances and extraction of returned parameter values. It also catches CQL exceptions and translates
|
||||
them to the generic, more informative, exception hierarchy defined in the `org.springframework.dao` package.
|
||||
The `CqlTemplate` class is the central class in the core CQL package.
|
||||
It handles the creation and release of resources.
|
||||
It performs the basic tasks of the core CQL workflow, such as statement creation and execution, and leaves application code to provide CQL and extract results.
|
||||
The `CqlTemplate` class executes CQL queries and update statements, performs iteration over `ResultSet` instances and extraction of returned parameter values.
|
||||
It also catches CQL exceptions and translates them to the generic, more informative, exception hierarchy defined in the `org.springframework.dao` package.
|
||||
|
||||
When you use the `CqlTemplate` for your code, you need only implement callback interfaces, which have a clearly
|
||||
defined contract. Given a `Connection`, the `PreparedStatementCreator` callback interface creates a prepared statement
|
||||
with the provided CQL and any necessary parameter arguments. The `RowCallbackHandler` interface extracts values
|
||||
from each row of a `ResultSet`.
|
||||
When you use the `CqlTemplate` for your code, you need only implement callback interfaces, which have a clearly defined contract.
|
||||
Given a `Connection`, the `PreparedStatementCreator` callback interface creates a prepared statement with the provided CQL and any necessary parameter arguments.
|
||||
The `RowCallbackHandler` interface extracts values from each row of a `ResultSet`.
|
||||
|
||||
The `CqlTemplate` can be used within a DAO implementation through direct instantiation with a `SessionFactory` reference
|
||||
or be configured in the Spring container and given to DAOs as a bean reference. `CqlTemplate` is a foundational building
|
||||
block for <<cassandra-template,`CassandraTemplate`>>.
|
||||
The `CqlTemplate` can be used within a DAO implementation through direct instantiation with a `SessionFactory` reference or be configured in the Spring container and given to DAOs as a bean reference. `CqlTemplate` is a foundational building block for <<cassandra-template,`CassandraTemplate`>>.
|
||||
|
||||
All CQL issued by this class is logged at the `DEBUG` level under the category corresponding to the fully-qualified class
|
||||
name of the template instance (typically `CqlTemplate`, but it may be different if you use a custom subclass
|
||||
of the `CqlTemplate` class).
|
||||
All CQL issued by this class is logged at the `DEBUG` level under the category corresponding to the fully-qualified class name of the template instance (typically `CqlTemplate`, but it may be different if you use a custom subclass of the `CqlTemplate` class).
|
||||
|
||||
You can control fetch size, consistency level, and retry policy defaults by configuring these parameters
|
||||
on the CQL API instances: `CqlTemplate`, `AsyncCqlTemplate`, and `ReactiveCqlTemplate`. Defaults apply if the particular
|
||||
query option is not set.
|
||||
You can control fetch size, consistency level, and retry policy defaults by configuring these parameters on the CQL API instances: `CqlTemplate`, `AsyncCqlTemplate`, and `ReactiveCqlTemplate`.
|
||||
Defaults apply if the particular query option is not set.
|
||||
|
||||
NOTE: `CqlTemplate` comes in different execution model flavors. The basic `CqlTemplate` uses a blocking execution model.
|
||||
NOTE: `CqlTemplate` comes in different execution model flavors.
|
||||
The basic `CqlTemplate` uses a blocking execution model.
|
||||
You can use `AsyncCqlTemplate` for asynchronous execution and synchronization with `ListenableFuture` instances or
|
||||
<<cassandra.reactive.cql-template,`ReactiveCqlTemplate`>> for reactive execution.
|
||||
|
||||
[[cassandracql-template.examples]]
|
||||
=== Examples of `CqlTemplate` Class Usage
|
||||
|
||||
This section provides some examples of the `CqlTemplate` class in action. These examples are not an exhaustive list
|
||||
of all of the functionality exposed by the `CqlTemplate`. See the https://docs.spring.io/spring-data/cassandra/docs/{version}/api/[Javadoc] for that.
|
||||
This section provides some examples of the `CqlTemplate` class in action.
|
||||
These examples are not an exhaustive list of all of the functionality exposed by the `CqlTemplate`.
|
||||
See the https://docs.spring.io/spring-data/cassandra/docs/{version}/api/[Javadoc] for that.
|
||||
|
||||
[[cassandra.cql-template.examples.query]]
|
||||
==== Querying (SELECT) with `CqlTemplate`
|
||||
@@ -600,9 +593,7 @@ include::../{example-root}/CqlTemplateExamples.java[tags=listOfRowMapper]
|
||||
----
|
||||
====
|
||||
|
||||
If the last two snippets of code actually existed in the same application, it would make sense to remove the
|
||||
duplication present in the two `RowMapper` anonymous inner classes and extract them out into a single class
|
||||
(typically a `static` nested class) that can then be referenced by DAO methods.
|
||||
If the last two snippets of code actually existed in the same application, it would make sense to remove the duplication present in the two `RowMapper` anonymous inner classes and extract them out into a single class (typically a `static` nested class) that can then be referenced by DAO methods.
|
||||
|
||||
For example, it might be better to write the last code snippet as follows:
|
||||
|
||||
@@ -616,8 +607,8 @@ include::../{example-root}/CqlTemplateExamples.java[tags=findAllActors]
|
||||
[[cassandra.cql-template.examples.update]]
|
||||
==== `INSERT`, `UPDATE`, and `DELETE` with `CqlTemplate`
|
||||
|
||||
You can use the `execute(…)` method to perform `INSERT`, `UPDATE`, and `DELETE` operations. Parameter values are usually provided
|
||||
as variable arguments or, alternatively, as an object array.
|
||||
You can use the `execute(…)` method to perform `INSERT`, `UPDATE`, and `DELETE` operations.
|
||||
Parameter values are usually provided as variable arguments or, alternatively, as an object array.
|
||||
|
||||
The following example shows how to perform an `INSERT` operation with `CqlTemplate`:
|
||||
|
||||
@@ -667,12 +658,11 @@ include::exception-translation.adoc[]
|
||||
[[cassandra.connections]]
|
||||
== Controlling Cassandra Connections
|
||||
|
||||
Applications connect to Apache Cassandra by using `CqlSession` objects. A Cassandra `CqlSession` keeps track of
|
||||
multiple connections to the individual nodes and is designed to be a thread-safe, long-lived object.
|
||||
Applications connect to Apache Cassandra by using `CqlSession` objects.
|
||||
A Cassandra `CqlSession` keeps track of multiple connections to the individual nodes and is designed to be a thread-safe, long-lived object.
|
||||
Usually, you can use a single `CqlSession` for the whole application.
|
||||
|
||||
Spring acquires a Cassandra `CqlSession` through a `SessionFactory`. `SessionFactory` is part of
|
||||
Spring Data for Apache Cassandra and is a generalized connection factory.
|
||||
Spring acquires a Cassandra `CqlSession` through a `SessionFactory`. `SessionFactory` is part of Spring Data for Apache Cassandra and is a generalized connection factory.
|
||||
It lets the container or framework hide connection handling and routing issues from the application code.
|
||||
|
||||
The following example shows how to configure a default `SessionFactory`:
|
||||
@@ -686,9 +676,9 @@ CqlTemplate template = new CqlTemplate();
|
||||
template.setSessionFactory(new DefaultSessionFactory(session));
|
||||
----
|
||||
|
||||
`CqlTemplate` and other Template API implementations obtain a `CqlSession` for each operation. Due to their
|
||||
long-lived nature, sessions are not closed after invoking the desired operation. Responsibility for proper
|
||||
resource disposal lies with the container or framework that uses the session.
|
||||
`CqlTemplate` and other Template API implementations obtain a `CqlSession` for each operation.
|
||||
Due to their long-lived nature, sessions are not closed after invoking the desired operation.
|
||||
Responsibility for proper resource disposal lies with the container or framework that uses the session.
|
||||
|
||||
You can find various `SessionFactory` implementations within the `org.springframework.data.cassandra.core.cql.session`
|
||||
package.
|
||||
@@ -696,50 +686,43 @@ package.
|
||||
[[cassandra.template]]
|
||||
== Introduction to `CassandraTemplate`
|
||||
|
||||
The `CassandraTemplate` class, located in the `org.springframework.data.cassandra` package, is the central class
|
||||
in Spring's Cassandra support and provides a rich feature set to interact with the database. The template offers
|
||||
convenience operations to create, update, delete, and query Cassandra, and provides a mapping between your domain objects
|
||||
and rows in Cassandra tables.
|
||||
The `CassandraTemplate` class, located in the `org.springframework.data.cassandra` package, is the central class in Spring's Cassandra support and provides a rich feature set to interact with the database.
|
||||
The template offers convenience operations to create, update, delete, and query Cassandra, and provides a mapping between your domain objects and rows in Cassandra tables.
|
||||
|
||||
NOTE: Once configured, `CassandraTemplate` is thread-safe and can be reused across multiple instances.
|
||||
|
||||
The mapping between rows in Cassandra and application domain classes is done by delegating to an implementation
|
||||
of the `CassandraConverter` interface. Spring provides a default implementation, `MappingCassandraConverter`,
|
||||
but you can also write your own custom converter. See the section on
|
||||
The mapping between rows in Cassandra and application domain classes is done by delegating to an implementation of the `CassandraConverter` interface.
|
||||
Spring provides a default implementation, `MappingCassandraConverter`, but you can also write your own custom converter.
|
||||
See the section on
|
||||
<<mapping-chapter,Cassandra conversion>> for more detailed information.
|
||||
|
||||
The `CassandraTemplate` class implements the `CassandraOperations` interface. In as much as possible, the methods
|
||||
on `CassandraOperations` are named after methods available in Cassandra to make the API familiar to
|
||||
developers who are already familiar with Cassandra.
|
||||
The `CassandraTemplate` class implements the `CassandraOperations` interface.
|
||||
In as much as possible, the methods on `CassandraOperations` are named after methods available in Cassandra to make the API familiar to developers who are already familiar with Cassandra.
|
||||
|
||||
For example, you can find methods such as `select`, `insert`, `delete`, and `update`. The design goal was to make it
|
||||
as easy as possible to transition between the use of the base Cassandra driver and `CassandraOperations`.
|
||||
A major difference between the two APIs is that `CassandraOperations` can be passed domain objects instead of CQL
|
||||
and query objects.
|
||||
For example, you can find methods such as `select`, `insert`, `delete`, and `update`.
|
||||
The design goal was to make it as easy as possible to transition between the use of the base Cassandra driver and `CassandraOperations`.
|
||||
A major difference between the two APIs is that `CassandraOperations` can be passed domain objects instead of CQL and query objects.
|
||||
|
||||
NOTE: The preferred way to reference operations on a `CassandraTemplate` instance is through the
|
||||
`CassandraOperations` interface.
|
||||
|
||||
The default converter implementation used by `CassandraTemplate` is `MappingCassandraConverter`.
|
||||
While `MappingCassandraConverter` can use additional metadata to specify the mapping of objects
|
||||
to rows, it can also convert objects that contain no additional metadata by using some conventions
|
||||
for the mapping of fields and table names. These conventions, as well as the use of mapping annotations, are explained
|
||||
in the <<mapping.chapter,"`Mapping`" chapter>>.
|
||||
While `MappingCassandraConverter` can use additional metadata to specify the mapping of objects to rows, it can also convert objects that contain no additional metadata by using some conventions for the mapping of fields and table names.
|
||||
These conventions, as well as the use of mapping annotations, are explained in the <<mapping.chapter,"`Mapping`" chapter>>.
|
||||
|
||||
Another central feature of `CassandraTemplate` is exception translation of exceptions thrown in the Cassandra
|
||||
Java driver into Spring's portable Data Access Exception hierarchy. See the section on
|
||||
Another central feature of `CassandraTemplate` is exception translation of exceptions thrown in the Cassandra Java driver into Spring's portable Data Access Exception hierarchy.
|
||||
See the section on
|
||||
<<cassandra.exception,exception translation>> for more information.
|
||||
|
||||
NOTE: The Template API has different execution model flavors. The basic `CassandraTemplate` uses a
|
||||
blocking (imperative-synchronous) execution model. You can use `AsyncCassandraTemplate` for asynchronous execution and synchronization
|
||||
with `ListenableFuture` instances or <<cassandra.reactive.template,`ReactiveCassandraTemplate`>> for reactive execution.
|
||||
NOTE: The Template API has different execution model flavors.
|
||||
The basic `CassandraTemplate` uses a blocking (imperative-synchronous) execution model.
|
||||
You can use `AsyncCassandraTemplate` for asynchronous execution and synchronization with `ListenableFuture` instances or <<cassandra.reactive.template,`ReactiveCassandraTemplate`>> for reactive execution.
|
||||
|
||||
[[cassandra.template.instantiating]]
|
||||
=== Instantiating CassandraTemplate
|
||||
|
||||
`CassandraTemplate` should always be configured as a Spring bean, although we show an example earlier where
|
||||
you can instantiate it directly. However, because we are assuming the context of making a Spring module, we assume the presence of
|
||||
the Spring container.
|
||||
`CassandraTemplate` should always be configured as a Spring bean, although we show an example earlier where you can instantiate it directly.
|
||||
However, because we are assuming the context of making a Spring module, we assume the presence of the Spring container.
|
||||
|
||||
There are two ways to get a `CassandraTemplate`, depending on how you load you Spring `ApplicationContext`:
|
||||
|
||||
@@ -761,8 +744,7 @@ private CassandraOperations cassandraOperations;
|
||||
====
|
||||
|
||||
As with all Spring autowiring, this assumes there is only one bean of type `CassandraOperations` in the `ApplicationContext`.
|
||||
If you have multiple `CassandraTemplate` beans (which is the case if you work with multiple keyspaces
|
||||
in the same project), then you can use the `@Qualifier` annotation to designate the bean you want to autowire.
|
||||
If you have multiple `CassandraTemplate` beans (which is the case if you work with multiple keyspaces in the same project), then you can use the `@Qualifier` annotation to designate the bean you want to autowire.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -789,31 +771,30 @@ CassandraOperations cassandraOperations = applicationContext.getBean("cassandraT
|
||||
[[cassandra-template.save-update-remove]]
|
||||
== Saving, Updating, and Removing Rows
|
||||
|
||||
`CassandraTemplate` provides a simple way for you to save, update, and delete your domain objects and map those objects
|
||||
to tables managed in Cassandra.
|
||||
`CassandraTemplate` provides a simple way for you to save, update, and delete your domain objects and map those objects to tables managed in Cassandra.
|
||||
|
||||
[[cassandra.template.type-mapping]]
|
||||
=== Type Mapping
|
||||
|
||||
Spring Data for Apache Cassandra relies on the DataStax Java driver's `CodecRegistry` to ensure type support. As types
|
||||
are added or changed, the Spring Data for Apache Cassandra module continues to function without requiring changes.
|
||||
Spring Data for Apache Cassandra relies on the DataStax Java driver's `CodecRegistry` to ensure type support.
|
||||
As types are added or changed, the Spring Data for Apache Cassandra module continues to function without requiring changes.
|
||||
See https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cql_data_types_c.html[CQL data types]
|
||||
and "`<<mapping-conversion>>`" for the current type mapping matrix.
|
||||
|
||||
[[cassandra.template.insert-update]]
|
||||
=== Methods for Inserting and Updating rows
|
||||
|
||||
`CassandraTemplate` has several convenient methods for saving and inserting your objects. To have more
|
||||
fine-grained control over the conversion process, you can register Spring `Converter` instances with the `MappingCassandraConverter`
|
||||
`CassandraTemplate` has several convenient methods for saving and inserting your objects.
|
||||
To have more fine-grained control over the conversion process, you can register Spring `Converter` instances with the `MappingCassandraConverter`
|
||||
(for example, `Converter<Row, Person>`).
|
||||
|
||||
NOTE: The difference between insert and update operations is that `INSERT` operations do not insert `null` values.
|
||||
|
||||
The simple case of using the `INSERT` operation is to save a POJO. In this case, the table name is determined by
|
||||
the simple class name (not the fully qualified class name). The table to store the object can be overridden by
|
||||
using mapping metadata.
|
||||
The simple case of using the `INSERT` operation is to save a POJO. In this case, the table name is determined by the simple class name (not the fully qualified class name).
|
||||
The table to store the object can be overridden by using mapping metadata.
|
||||
|
||||
When inserting or updating, the `id` property must be set. Apache Cassandra has no means to generate an ID.
|
||||
When inserting or updating, the `id` property must be set.
|
||||
Apache Cassandra has no means to generate an ID.
|
||||
|
||||
The following example uses the save operation and retrieves its contents:
|
||||
|
||||
@@ -835,14 +816,12 @@ Person queriedBob = cassandraTemplate.selectOneById(query(where("age").is(33)),
|
||||
You can use the following operations to insert and save:
|
||||
|
||||
* `void` *insert* `(Object objectToSave)`: Inserts the object in an Apache Cassandra table.
|
||||
* `WriteResult` *insert* `(Object objectToSave, InsertOptions options)`: Inserts the object in an Apache Cassandra table and
|
||||
applies `InsertOptions`.
|
||||
* `WriteResult` *insert* `(Object objectToSave, InsertOptions options)`: Inserts the object in an Apache Cassandra table and applies `InsertOptions`.
|
||||
|
||||
You can use the following update operations:
|
||||
|
||||
* `void` *update* `(Object objectToSave)`: Updates the object in an Apache Cassandra table.
|
||||
* `WriteResult` *update* `(Object objectToSave, UpdateOptions options)`: Updates the object in an Apache Cassandra table and
|
||||
applies `UpdateOptions`.
|
||||
* `WriteResult` *update* `(Object objectToSave, UpdateOptions options)`: Updates the object in an Apache Cassandra table and applies `UpdateOptions`.
|
||||
|
||||
You can also use the old fashioned way and write your own CQL statements, as the following example shows:
|
||||
|
||||
@@ -853,15 +832,14 @@ String cql = "INSERT INTO person (age, name) VALUES (39, 'Bob')";
|
||||
cassandraTemplate().getCqlOperations().execute(cql);
|
||||
----
|
||||
|
||||
You can also configure additional options such as TTL, consistency level, and lightweight transactions
|
||||
when using `InsertOptions` and `UpdateOptions`.
|
||||
You can also configure additional options such as TTL, consistency level, and lightweight transactions when using `InsertOptions` and `UpdateOptions`.
|
||||
|
||||
[[cassandra.template.insert-update.table]]
|
||||
==== Which Table Are My Rows Inserted into?
|
||||
|
||||
You can manage the table name that is used for operating on the tables in two ways. The default table name
|
||||
is the simple class name changed to start with a lower-case letter. So, an instance of
|
||||
the `com.example.Person` class would be stored in the `person` table.
|
||||
You can manage the table name that is used for operating on the tables in two ways.
|
||||
The default table name is the simple class name changed to start with a lower-case letter.
|
||||
So, an instance of the `com.example.Person` class would be stored in the `person` table.
|
||||
The second way is to specify a table name in the `@Table` annotation.
|
||||
|
||||
[[cassandra.template.batch]]
|
||||
@@ -886,8 +864,7 @@ The following methods in the `CassandraTemplate` interface support this function
|
||||
|
||||
For updates, you can select to update a number of rows.
|
||||
|
||||
The following example shows updating a single account object by adding a one-time $50.00 bonus to the balance
|
||||
with the `+` assignment:
|
||||
The following example shows updating a single account object by adding a one-time $50.00 bonus to the balance with the `+` assignment:
|
||||
|
||||
.Updating rows using `CasandraTemplate`
|
||||
====
|
||||
@@ -914,24 +891,22 @@ Most methods return the `Update` object to provide a fluent API for code styling
|
||||
|
||||
The update method can update rows, as follows:
|
||||
|
||||
* `boolean` *update* `(Query query, Update update, Class<?> entityClass)`: Updates a selection of objects in
|
||||
the Apache Cassandra table.
|
||||
* `boolean` *update* `(Query query, Update update, Class<?> entityClass)`: Updates a selection of objects in the Apache Cassandra table.
|
||||
|
||||
[[cassandra.template.update.update]]
|
||||
==== Methods for the Update class
|
||||
|
||||
The `Update` class can be used with a little 'syntax sugar', as its methods are meant to be chained together.
|
||||
Also, you can kick-start the creation of a new `Update` instance with the
|
||||
static method `public static Update update(String key, Object value)` and by using static imports.
|
||||
Also, you can kick-start the creation of a new `Update` instance with the static method `public static Update update(String key, Object value)` and by using static imports.
|
||||
|
||||
The `Update` class has the following methods:
|
||||
|
||||
* `AddToBuilder` *addTo* `(String columnName)` `AddToBuilder` entry-point:
|
||||
** Update `prepend(Object value)`: Prepends a collection value to the existing collection by using the `+` update assignment.
|
||||
** Update `prepend(Object value)`: Prepends a collection value to the existing collection by using the `+` update assignment.
|
||||
** Update `prependAll(Object... values)`: Prepends all collection values to the existing collection by using the `+` update assignment.
|
||||
** Update `append(Object value)`: Appends a collection value to the existing collection by using the `+` update assignment.
|
||||
** Update `append(Object value)`: Appends a collection value to the existing collection by using the `+` update assignment.
|
||||
** Update `append(Object... values)`: Appends all collection values to the existing collection by using the `+` update assignment.
|
||||
** Update `entry(Object key, Object value)`: Adds a map entry by using the `+` update assignment.
|
||||
** Update `entry(Object key, Object value)`: Adds a map entry by using the `+` update assignment.
|
||||
** Update `addAll(Map<? extends Object, ? extends Object> map)`: Adds all map entries to the map by using the `+` update assignment.
|
||||
* `Update` *remove* `(String columnName, Object value)`: Removes the value from the collection by using the `-` update assignment.
|
||||
* `Update` *clear* `(String columnName)`: Clears the collection.
|
||||
@@ -939,8 +914,8 @@ The `Update` class has the following methods:
|
||||
* `Update` *decrement* `(String columnName, Number delta)`: Updates by using the `-` update assignment.
|
||||
* `Update` *set* `(String columnName, Object value)`: Updates by using the `=` update assignment.
|
||||
* `SetBuilder` *set* `(String columnName)` `SetBuilder` entry-point:
|
||||
** Update `atIndex(int index).to(Object value)`: Sets a collection at the given index to a value using the `=` update assignment.
|
||||
** Update `atKey(String object).to(Object value)`: Sets a map entry at the given key to a value the `=` update assignment.
|
||||
** Update `atIndex(int index).to(Object value)`: Sets a collection at the given index to a value using the `=` update assignment.
|
||||
** Update `atKey(String object).to(Object value)`: Sets a map entry at the given key to a value the `=` update assignment.
|
||||
|
||||
The following listing shows a few update examples:
|
||||
|
||||
@@ -958,7 +933,8 @@ Update.empty().addTo("key").appendAll("Spring", "Data");
|
||||
----
|
||||
====
|
||||
|
||||
Note that `Update` is immutable once created. Invoking methods creates new immutable (intermediate) `Update` objects.
|
||||
Note that `Update` is immutable once created.
|
||||
Invoking methods creates new immutable (intermediate) `Update` objects.
|
||||
|
||||
[[cassandra.template.delete]]
|
||||
=== Methods for Removing Rows
|
||||
@@ -1003,8 +979,10 @@ template.save(tmp); // throws OptimisticLockingFailureException
|
||||
----
|
||||
<1> Intially insert document. `version` is set to `0`.
|
||||
<2> Load the just inserted document. `version` is still `0`.
|
||||
<3> Update the document with `version = 0`. Set the `lastname` and bump `version` to `1`.
|
||||
<4> Try to update the previously loaded document that still has `version = 0`. The operation fails with an `OptimisticLockingFailureException`, as the current `version` is `1`.
|
||||
<3> Update the document with `version = 0`.
|
||||
Set the `lastname` and bump `version` to `1`.
|
||||
<4> Try to update the previously loaded document that still has `version = 0`.
|
||||
The operation fails with an `OptimisticLockingFailureException`, as the current `version` is `1`.
|
||||
====
|
||||
|
||||
NOTE: Optimistic Locking is only supported with single-entity operations and not for batch operations.
|
||||
@@ -1012,21 +990,19 @@ NOTE: Optimistic Locking is only supported with single-entity operations and not
|
||||
[[cassandra.template.query]]
|
||||
== Querying Rows
|
||||
|
||||
You can express your queries by using the `Query` and `Criteria` classes, which have method names that reflect
|
||||
the native Cassandra predicate operator names, such as `lt`, `lte`, `is`, and others.
|
||||
You can express your queries by using the `Query` and `Criteria` classes, which have method names that reflect the native Cassandra predicate operator names, such as `lt`, `lte`, `is`, and others.
|
||||
|
||||
The `Query` and `Criteria` classes follow a fluent API style so that you can easily chain together multiple method criteria
|
||||
and queries while having easy-to-understand code. Static imports are used in Java when creating `Query`
|
||||
The `Query` and `Criteria` classes follow a fluent API style so that you can easily chain together multiple method criteria and queries while having easy-to-understand code.
|
||||
Static imports are used in Java when creating `Query`
|
||||
and `Criteria` instances to improve readability.
|
||||
|
||||
|
||||
[[cassandra.template.query.table]]
|
||||
=== Querying Rows in a Table
|
||||
|
||||
In earlier sections, we saw how to retrieve a single object by using the `selectOneById` method on `CassandraTemplate`.
|
||||
Doing so returns a single domain object. We can also query for a collection of rows to be returned as a
|
||||
list of domain objects. Assuming we have a number of `Person` objects with name and age values stored as rows in a table
|
||||
and that each person has an account balance, we can now run a query by using the following code:
|
||||
Doing so returns a single domain object.
|
||||
We can also query for a collection of rows to be returned as a list of domain objects.
|
||||
Assuming we have a number of `Person` objects with name and age values stored as rows in a table and that each person has an account balance, we can now run a query by using the following code:
|
||||
|
||||
.Querying for rows using `CassandraTemplate`
|
||||
====
|
||||
@@ -1042,13 +1018,13 @@ List<Person> result = cassandraTemplate.select(query(where("age").is(50))
|
||||
----
|
||||
====
|
||||
|
||||
The `select`, `selectOne`, and `stream` methods take a `Query` object as a parameter. This object defines the criteria
|
||||
and options used to perform the query. The criteria is specified by using a `Criteria` object that has
|
||||
a static factory method named `where` that instantiates a new `Criteria` object. We recommend using a static import
|
||||
for `org.springframework.data.cassandra.core.query.Criteria.where` and `Query.query`, to make the query more readable.
|
||||
The `select`, `selectOne`, and `stream` methods take a `Query` object as a parameter.
|
||||
This object defines the criteria and options used to perform the query.
|
||||
The criteria is specified by using a `Criteria` object that has a static factory method named `where` that instantiates a new `Criteria` object.
|
||||
We recommend using a static import for `org.springframework.data.cassandra.core.query.Criteria.where` and `Query.query`, to make the query more readable.
|
||||
|
||||
This query should return a list of `Person` objects that meet the specified criteria. The `Criteria` class has
|
||||
the following methods that correspond to the operators provided in Apache Cassandra:
|
||||
This query should return a list of `Person` objects that meet the specified criteria.
|
||||
The `Criteria` class has the following methods that correspond to the operators provided in Apache Cassandra:
|
||||
|
||||
[[cassandra.template.query.criteria]]
|
||||
==== Methods for the Criteria class
|
||||
@@ -1081,7 +1057,8 @@ The `Query` class has some additional methods that you can use to provide option
|
||||
* `Query` *sort* `(Sort sort)`: Used to provide a sort definition for the results.
|
||||
* `Query` *withAllowFiltering* `()`: Used to render `ALLOW FILTERING` queries.
|
||||
|
||||
`Query` is immutable once created. Invoking methods creates new immutable (intermediate) `Query` objects.
|
||||
`Query` is immutable once created.
|
||||
Invoking methods creates new immutable (intermediate) `Query` objects.
|
||||
|
||||
[[cassandra.template.query.rows]]
|
||||
=== Methods for Querying for Rows
|
||||
@@ -1101,15 +1078,15 @@ The query methods must specify the target type `T` that is returned.
|
||||
[[cassandra.template.query.fluent-template-api]]
|
||||
=== Fluent Template API
|
||||
|
||||
The `CassandraOperations` interface is one of the central components when it comes to more low-level interaction
|
||||
with Apache Cassandra. It offers a wide range of methods. You can find multiple overloads for every method.
|
||||
The `CassandraOperations` interface is one of the central components when it comes to more low-level interaction with Apache Cassandra.
|
||||
It offers a wide range of methods.
|
||||
You can find multiple overloads for every method.
|
||||
Most of them cover optional (nullable) parts of the API.
|
||||
|
||||
`FluentCassandraOperations` provide a more narrow interface for common methods of `CassandraOperations`
|
||||
providing a more readable, fluent API. The entry points (`query(…)`, `insert(…)`, `update(…)`, and `delete(…)`)
|
||||
follow a natural naming scheme based on the operation to execute. Moving on from the entry point, the API
|
||||
is designed to offer only context-dependent methods that guide the developer towards a terminating method
|
||||
that invokes the actual `CassandraOperation`. The following example shows the fluent API:
|
||||
providing a more readable, fluent API. The entry points (`query(…)`, `insert(…)`, `update(…)`, and `delete(…)`) follow a natural naming scheme based on the operation to execute.
|
||||
Moving on from the entry point, the API is designed to offer only context-dependent methods that guide the developer towards a terminating method that invokes the actual `CassandraOperation`.
|
||||
The following example shows the fluent API:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -1121,9 +1098,9 @@ List<SWCharacter> all = ops.query(SWCharacter.class)
|
||||
<1> Skip this step if `SWCharacter` defines the table name with `@Table` or if using the class name as the table name is not a problem.
|
||||
====
|
||||
|
||||
If a table in Cassandra holds entities of different types, such as a `Jedi` within a Table of `SWCharacters`, you can use
|
||||
different types to map the query result. You can use `as(Class<?> targetType)` to map results to a different target type,
|
||||
while `query(Class<?> entityType)` still applies to the query and table name. The following example uses the `query` and `as` methods:
|
||||
If a table in Cassandra holds entities of different types, such as a `Jedi` within a Table of `SWCharacters`, you can use different types to map the query result.
|
||||
You can use `as(Class<?> targetType)` to map results to a different target type, while `query(Class<?> entityType)` still applies to the query and table name.
|
||||
The following example uses the `query` and `as` methods:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -1137,13 +1114,10 @@ List<Jedi> all = ops.query(SWCharacter.class) <1>
|
||||
<2> Resulting rows are mapped into `Jedi`.
|
||||
====
|
||||
|
||||
TIP: You can directly apply <<projections>> to resulting documents by providing only the `interface` type
|
||||
through `as(Class<?>)`.
|
||||
TIP: You can directly apply <<projections>> to resulting documents by providing only the `interface` type through `as(Class<?>)`.
|
||||
|
||||
The terminating methods (`first()`, `one()`, `all()`, and `stream()`) handle switching between retrieving a single entity and retrieving multiple entities as `List` or `Stream` and similar operations.
|
||||
|
||||
WARNING: The new fluent template API methods (that is, `query(..)`, `insert(..)`, `update(..)`, and `delete(..)`)
|
||||
use effectively thread-safe supporting objects to compose the CQL statement. However, it comes
|
||||
at the added cost of additional young-gen JVM heap overhead, since the design is based on final fields
|
||||
for the various CQL statement components and construction on mutation. You should be careful when possibly
|
||||
inserting or deleting a large number of objects (such as inside of a loop, for instance).
|
||||
WARNING: The new fluent template API methods (that is, `query(..)`, `insert(..)`, `update(..)`, and `delete(..)`) use effectively thread-safe supporting objects to compose the CQL statement.
|
||||
However, it comes at the added cost of additional young-gen JVM heap overhead, since the design is based on final fields for the various CQL statement components and construction on mutation.
|
||||
You should be careful when possibly inserting or deleting a large number of objects (such as inside of a loop, for instance).
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
To have more fine-grained control over the mapping process, you can register Spring `Converters` with
|
||||
`CassandraConverter` implementations, such as `MappingCassandraConverter`.
|
||||
|
||||
`MappingCassandraConverter` first checks to see whether any Spring `Converters` can handle
|
||||
a specific class before attempting to map the object itself. To "'hijack'" the normal mapping strategies
|
||||
of the `MappingCassandraConverter` (perhaps for increased performance or other custom mapping needs), you
|
||||
need to create an implementation of the Spring `Converter` interface and register it with
|
||||
the `MappingCassandraConverter`.
|
||||
`MappingCassandraConverter` first checks to see whether any Spring `Converters` can handle a specific class before attempting to map the object itself.
|
||||
To "'hijack'" the normal mapping strategies of the `MappingCassandraConverter` (perhaps for increased performance or other custom mapping needs), you need to create an implementation of the Spring `Converter` interface and register it with the `MappingCassandraConverter`.
|
||||
|
||||
[[customconversions.writer]]
|
||||
=== Saving by Using a Registered Spring Converter
|
||||
@@ -28,8 +25,7 @@ include::../{example-root}/PersonWriteConverter.java[tags=class]
|
||||
|
||||
Similar to how you can combine saving and converting, you can also combine reading and converting.
|
||||
|
||||
The following example uses a `Converter` that converts a `java.lang.String` into a `Person` object
|
||||
with Jackson 2:
|
||||
The following example uses a `Converter` that converts a `java.lang.String` into a `Person` object with Jackson 2:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -40,8 +36,8 @@ include::../{example-root}/PersonReadConverter.java[tags=class]
|
||||
=== Registering Spring Converters with `CassandraConverter`
|
||||
|
||||
Spring Data for Apache Cassandra Java configuration provides a convenient way to register Spring `Converter` instances:
|
||||
`MappingCassandraConverter`. The following configuration snippet shows how to manually register converters
|
||||
as well as configure `CustomConversions`:
|
||||
`MappingCassandraConverter`.
|
||||
The following configuration snippet shows how to manually register converters as well as configure `CustomConversions`:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
== Exception Translation
|
||||
|
||||
The Spring Framework provides exception translation for a wide variety of database and mapping technologies.
|
||||
This has traditionally been for JDBC and JPA. Spring Data for Apache Cassandra extends this feature to Apache Cassandra
|
||||
by providing an implementation of the `org.springframework.dao.support.PersistenceExceptionTranslator` interface.
|
||||
This has traditionally been for JDBC and JPA. Spring Data for Apache Cassandra extends this feature to Apache Cassandra by providing an implementation of the `org.springframework.dao.support.PersistenceExceptionTranslator` interface.
|
||||
|
||||
The motivation behind mapping to Spring's {spring-framework-docs}html/dao.html#dao-exceptions[consistent data access exception hierarchy]
|
||||
is to let you write portable and descriptive exception handling code without resorting to coding against
|
||||
and handling specific Cassandra exceptions. All of Spring's data access exceptions are inherited from the
|
||||
`DataAccessException` class, so you can be sure that you can catch all database-related exceptions
|
||||
within a single try-catch block.
|
||||
is to let you write portable and descriptive exception handling code without resorting to coding against and handling specific Cassandra exceptions.
|
||||
All of Spring's data access exceptions are inherited from the
|
||||
`DataAccessException` class, so you can be sure that you can catch all database-related exceptions within a single try-catch block.
|
||||
|
||||
@@ -13,9 +13,8 @@ This part of the reference documentation explains the core functionality offered
|
||||
|
||||
Spring Data for Apache Cassandra allows interaction on both the CQL and the entity level.
|
||||
|
||||
The value provided by the Spring Data for Apache Cassandra abstraction is perhaps best shown by
|
||||
the sequence of actions outlined in the table below. The table shows which actions Spring take care of
|
||||
and which actions are the responsibility of you, the application developer.
|
||||
The value provided by the Spring Data for Apache Cassandra abstraction is perhaps best shown by the sequence of actions outlined in the table below.
|
||||
The table shows which actions Spring take care of and which actions are the responsibility of you, the application developer.
|
||||
|
||||
[[cassandra.modules.who-does-what]]
|
||||
.Spring Data for Apache Cassandra (CQL Core)- who does what?
|
||||
@@ -59,25 +58,24 @@ and which actions are the responsibility of you, the application developer.
|
||||
|
|
||||
|===
|
||||
|
||||
The core CQL support takes care of all the low-level details that can make Cassandra and CQL such a tedious API
|
||||
with which to develop. Using mapped entity objects allows schema generation, object mapping, and repository support.
|
||||
The core CQL support takes care of all the low-level details that can make Cassandra and CQL such a tedious API with which to develop.
|
||||
Using mapped entity objects allows schema generation, object mapping, and repository support.
|
||||
|
||||
[[cassandra.choose-style]]
|
||||
=== Choosing an Approach for Cassandra Database Access
|
||||
|
||||
You can choose among several approaches to use as a basis for your Cassandra database access. Spring's support
|
||||
for Apache Cassandra comes in different flavors. Once you start using one of these approaches, you can still mix
|
||||
and match to include a feature from a different approach. The following approaches work well:
|
||||
You can choose among several approaches to use as a basis for your Cassandra database access.
|
||||
Spring's support for Apache Cassandra comes in different flavors.
|
||||
Once you start using one of these approaches, you can still mix and match to include a feature from a different approach.
|
||||
The following approaches work well:
|
||||
|
||||
* <<cassandra.cql-template,`CqlTemplate`>> and <<cassandra.reactive.cql-template,`ReactiveCqlTemplate`>> are the
|
||||
classic Spring CQL approach and the most popular. This is the "`lowest-level`" approach. Note that components like `CassandraTemplate`
|
||||
use `CqlTemplate` under-the-hood.
|
||||
* <<cassandra.template,`CassandraTemplate`>> wraps a `CqlTemplate` to provide query result-to-object mapping
|
||||
and the use of `SELECT`, `INSERT`, `UPDATE`, and `DELETE` methods instead of writing CQL statements. This approach
|
||||
provides better documentation and ease of use.
|
||||
* <<cassandra.reactive.template,`ReactiveCassandraTemplate`>> wraps a `ReactiveCqlTemplate` to provide query
|
||||
result-to-object mapping and the use of `SELECT`, `INSERT`, `UPDATE`, and `DELETE` methods instead of writing CQL statements.
|
||||
* <<cassandra.cql-template,`CqlTemplate`>> and <<cassandra.reactive.cql-template,`ReactiveCqlTemplate`>> are the classic Spring CQL approach and the most popular.
|
||||
This is the "`lowest-level`" approach.
|
||||
Note that components like `CassandraTemplate`
|
||||
use `CqlTemplate` under-the-hood.
|
||||
* <<cassandra.template,`CassandraTemplate`>> wraps a `CqlTemplate` to provide query result-to-object mapping and the use of `SELECT`, `INSERT`, `UPDATE`, and `DELETE` methods instead of writing CQL statements.
|
||||
This approach provides better documentation and ease of use.
|
||||
* Repository Abstraction lets you create repository declarations in your data access layer. The goal of
|
||||
Spring Data's repository abstraction is to significantly reduce the amount of boilerplate code required to implement
|
||||
data access layers for various persistence stores.
|
||||
* <<cassandra.reactive.template,`ReactiveCassandraTemplate`>> wraps a `ReactiveCqlTemplate` to provide query result-to-object mapping and the use of `SELECT`, `INSERT`, `UPDATE`, and `DELETE` methods instead of writing CQL statements.
|
||||
This approach provides better documentation and ease of use.
|
||||
* Repository Abstraction lets you create repository declarations in your data access layer.
|
||||
The goal of Spring Data's repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.
|
||||
|
||||
@@ -178,6 +178,7 @@ You can override it to tell the converter where to scan for classes annotated wi
|
||||
You can add additional converters to the `MappingCassandraConverter` by overriding the `customConversions` method.
|
||||
|
||||
NOTE: `AbstractCassandraConfiguration` creates a `CassandraTemplate` instance and registers it with the container under the name of `cassandraTemplate`.
|
||||
|
||||
[[mapping.usage]]
|
||||
== Metadata-based Mapping
|
||||
|
||||
@@ -362,7 +363,7 @@ Opposite to this behavior `USE_EMPTY` tries to create a new instance using eithe
|
||||
|
||||
.Sample Code of embedding objects
|
||||
====
|
||||
[source, java]
|
||||
[source,java]
|
||||
----
|
||||
public class User {
|
||||
|
||||
@@ -514,6 +515,7 @@ The `@Indexed` annotation can be applied to single properties of embedded entiti
|
||||
CAUTION: Index creation on session initialization may have a severe performance impact on application startup.
|
||||
|
||||
include::./converters.adoc[]
|
||||
|
||||
[[cassandra.mapping-usage.events]]
|
||||
== Lifecycle Events
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ into dedicated interfaces and templates.
|
||||
* Revised the `CqlTemplate` API to align with `JdbcTemplate`.
|
||||
* Removed the `CassandraOperations.selectBySimpleIds` method.
|
||||
* Used better names for `CassandraRepository`.
|
||||
* Removed SD Cassandra `ConsistencyLevel` and `RetryPolicy` types in favor of
|
||||
DataStax `ConsistencyLevel` and `RetryPolicy` types.
|
||||
* Removed SD Cassandra `ConsistencyLevel` and `RetryPolicy` types in favor of DataStax `ConsistencyLevel` and `RetryPolicy` types.
|
||||
* Refactored CQL specifications to value objects and configurators.
|
||||
* Refactored `QueryOptions` to be immutable objects.
|
||||
* Refactored `CassandraPersistentProperty` to single-column.
|
||||
@@ -28,8 +27,9 @@ DataStax `ConsistencyLevel` and `RetryPolicy` types.
|
||||
|
||||
== Merged Spring CQL and Spring Data Cassandra Modules
|
||||
|
||||
Spring CQL and Spring Data Cassandra are now merged into a single module. The standalone `spring-cql` module
|
||||
is no longer available. You can find all types merged into `spring-data-cassandra`.
|
||||
Spring CQL and Spring Data Cassandra are now merged into a single module.
|
||||
The standalone `spring-cql` module is no longer available.
|
||||
You can find all types merged into `spring-data-cassandra`.
|
||||
The following listing shows how to include `spring-data-cassandra` in your maven dependencies:
|
||||
|
||||
====
|
||||
@@ -61,21 +61,19 @@ With the merge, we merged all CQL packages into Spring Data Cassandra:
|
||||
|
||||
We split `CqlTemplate` and `CassandraTemplate` in three ways:
|
||||
|
||||
* `CassandraTemplate` is no longer a `CqlTemplate` but uses an instance that allows reuse and fine-grained control
|
||||
over fetch size, consistency levels, and retry policies. You can obtain the `CqlOperations` through
|
||||
`CassandraTemplate.getCqlOperations()`. Because of the change, dependency injection of `CqlTemplate` requires
|
||||
additional bean setup.
|
||||
* `CassandraTemplate` is no longer a `CqlTemplate` but uses an instance that allows reuse and fine-grained control over fetch size, consistency levels, and retry policies.
|
||||
You can obtain the `CqlOperations` through
|
||||
`CassandraTemplate.getCqlOperations()`.
|
||||
Because of the change, dependency injection of `CqlTemplate` requires additional bean setup.
|
||||
* `CqlTemplate` now reflects basic CQL operations instead of mixing high-level and low-level API calls (such as `count(…)`
|
||||
versus `execute(…)`) and the reduced method set is aligned with Spring Frameworks's `JdbcTemplate` with its convenient
|
||||
callback interfaces.
|
||||
versus `execute(…)`) and the reduced method set is aligned with Spring Frameworks's `JdbcTemplate` with its convenient callback interfaces.
|
||||
* Asynchronous methods are re-implemented on `AsyncCqlTemplate` and `AsyncCassandraTemplate` by using `ListenableFuture`.
|
||||
We removed `Cancellable` and the various async callback listeners. `ListenableFuture` is a flexible approach
|
||||
and allows transition into a `CompletableFuture`.
|
||||
We removed `Cancellable` and the various async callback listeners. `ListenableFuture` is a flexible approach and allows transition into a `CompletableFuture`.
|
||||
|
||||
== Removed `CassandraOperations.selectBySimpleIds()`
|
||||
|
||||
The method was removed because it did not support complex IDs. The newly introduced query DSL allows mapped
|
||||
and complex id's for single column Id's, as the following example shows:
|
||||
The method was removed because it did not support complex IDs.
|
||||
The newly introduced query DSL allows mapped and complex id's for single column Id's, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -86,8 +84,7 @@ cassandraTemplate.select(Query.query(Criteria.where("id").in(…)), Person.class
|
||||
|
||||
== Better names for `CassandraRepository`
|
||||
|
||||
We renamed `CassandraRepository` and `TypedIdCassandraRepository` to align Spring Data Cassandra naming with other
|
||||
Spring Data modules:
|
||||
We renamed `CassandraRepository` and `TypedIdCassandraRepository` to align Spring Data Cassandra naming with other Spring Data modules:
|
||||
|
||||
* Renamed `CassandraRepository` to `MapIdCassandraRepository`
|
||||
* Renamed `TypedIdCassandraRepository` to `CassandraRepository`
|
||||
@@ -95,23 +92,22 @@ Spring Data modules:
|
||||
|
||||
== Removed SD Cassandra `ConsistencyLevel` and `RetryPolicy` types in favor of DataStax `ConsistencyLevel` and `RetryPolicy` types
|
||||
|
||||
Spring Data Cassandra `ConsistencyLevel` and `RetryPolicy` have been removed. Please use the types provided by
|
||||
the DataStax driver.
|
||||
Spring Data Cassandra `ConsistencyLevel` and `RetryPolicy` have been removed.
|
||||
Please use the types provided by the DataStax driver.
|
||||
|
||||
The Spring Data Cassandra types restricted usage of available features provided in and allowed by the Cassandra native driver.
|
||||
As a result, the Spring Data Cassandra's types required an update each time newer functionality was introduced by the driver.
|
||||
|
||||
== Refactored CQL Specifications to Value Objects and Configurators
|
||||
|
||||
As much as possible, CQL specification types are now value types (such as `FieldSpecification`, `AlterColumnSpecification`),
|
||||
and objects are constructed by static factory methods. This allows immutability for simple value objects.
|
||||
Configurator objects (such as `AlterTableSpecification`) that operate on mandatory properties (such as a table name or
|
||||
keyspace name) are initially constructed through a a static factory method and allow further configuration until
|
||||
the desired state is created.
|
||||
As much as possible, CQL specification types are now value types (such as `FieldSpecification`, `AlterColumnSpecification`), and objects are constructed by static factory methods.
|
||||
This allows immutability for simple value objects.
|
||||
Configurator objects (such as `AlterTableSpecification`) that operate on mandatory properties (such as a table name or keyspace name) are initially constructed through a a static factory method and allow further configuration until the desired state is created.
|
||||
|
||||
== Refactored `QueryOptions` to be Immutable Objects
|
||||
|
||||
`QueryOptions` and `WriteOptions` are now immutable and can be created through builders. Methods accepting
|
||||
`QueryOptions` and `WriteOptions` are now immutable and can be created through builders.
|
||||
Methods accepting
|
||||
`QueryOptions` enforce non-null objects, which are available from static `empty()` factory methods.
|
||||
The following example shows how to use `QueryOptions.builder()`:
|
||||
|
||||
@@ -131,5 +127,5 @@ QueryOptions queryOptions = QueryOptions.builder()
|
||||
This change affects You only if you operate directly on the mapping model.
|
||||
|
||||
`CassandraPersistentProperty` allowed previously multiple column names to be bound for composite primary key use.
|
||||
Columns of a `CassandraPersistentProperty` are now reduced to a single column. Resolved composite primary keys
|
||||
map to a class through `MappingContext.getRequiredPersistentEntity(…)`.
|
||||
Columns of a `CassandraPersistentProperty` are now reduced to a single column.
|
||||
Resolved composite primary keys map to a class through `MappingContext.getRequiredPersistentEntity(…)`.
|
||||
|
||||
@@ -81,7 +81,8 @@ We generally recommend to create `CqlTemplate` and `CassandraTemplate` objects b
|
||||
----
|
||||
====
|
||||
|
||||
You will have to adapt your code in all places, where you use DataStax driver API directly. Typical cases include:
|
||||
You will have to adapt your code in all places, where you use DataStax driver API directly.
|
||||
Typical cases include:
|
||||
|
||||
* Implementations of `ResultSetExtractor`
|
||||
* Implementations of `RowCallbackHandler`
|
||||
|
||||
@@ -2,34 +2,30 @@
|
||||
= Reactive Cassandra Repositories
|
||||
|
||||
This chapter outlines the specialties handled by the reactive repository support for Apache Cassandra.
|
||||
It builds on the core repository infrastructure explained in <<cassandra.repositories>>, so
|
||||
you should have a good understanding of the basic concepts explained there.
|
||||
It builds on the core repository infrastructure explained in <<cassandra.repositories>>, so you should have a good understanding of the basic concepts explained there.
|
||||
|
||||
Reactive usage is broken up into two phases: Composition and Execution.
|
||||
|
||||
Calling repository methods lets you compose a reactive sequence by obtaining `Publisher` instances and applying operators.
|
||||
No I/O happens until you subscribe. Passing the reactive sequence to a reactive execution infrastructure,
|
||||
such as {spring-framework-docs}web.html#web-reactive[Spring WebFlux]
|
||||
or https://vertx.io/docs/vertx-reactive-streams/java/[Vert.x]), subscribes to the publisher and initiate
|
||||
the actual execution. See https://projectreactor.io/docs/core/release/reference/#reactive.subscribe[the Project reactor documentation] for more detail.
|
||||
|
||||
No I/O happens until you subscribe.
|
||||
Passing the reactive sequence to a reactive execution infrastructure, such as {spring-framework-docs}web.html#web-reactive[Spring WebFlux]
|
||||
or https://vertx.io/docs/vertx-reactive-streams/java/[Vert.x]), subscribes to the publisher and initiate the actual execution.
|
||||
See https://projectreactor.io/docs/core/release/reference/#reactive.subscribe[the Project reactor documentation] for more detail.
|
||||
|
||||
[[cassandra.reactive.repositories.libraries]]
|
||||
== Reactive Composition Libraries
|
||||
|
||||
The reactive space offers various reactive composition libraries. The most common libraries are
|
||||
The reactive space offers various reactive composition libraries.
|
||||
The most common libraries are
|
||||
https://github.com/ReactiveX/RxJava[RxJava] and https://projectreactor.io/[Project Reactor].
|
||||
|
||||
Spring Data for Apache Cassandra is built on top of the https://github.com/datastax/java-driver[DataStax Cassandra Driver].
|
||||
The driver is not reactive but the asynchronous capabilities allow us to adopt and expose the `Publisher` APIs
|
||||
to provide maximum interoperability by relying on the https://www.reactive-streams.org/[Reactive Streams] initiative.
|
||||
The driver is not reactive but the asynchronous capabilities allow us to adopt and expose the `Publisher` APIs to provide maximum interoperability by relying on the https://www.reactive-streams.org/[Reactive Streams] initiative.
|
||||
Static APIs, such as `ReactiveCassandraOperations`, are provided by using Project Reactor's `Flux` and `Mono` types.
|
||||
Project Reactor offers various adapters to convert reactive wrapper types (`Flux` to `Observable` and back),
|
||||
but conversion can easily clutter your code.
|
||||
Project Reactor offers various adapters to convert reactive wrapper types (`Flux` to `Observable` and back), but conversion can easily clutter your code.
|
||||
|
||||
Spring Data's repository abstraction is a dynamic API that is mostly defined by you and your requirements
|
||||
as you declare query methods. Reactive Cassandra repositories can be implemented by using either RxJava
|
||||
or Project Reactor wrapper types by extending from one of the library-specific repository interfaces:
|
||||
Spring Data's repository abstraction is a dynamic API that is mostly defined by you and your requirements as you declare query methods.
|
||||
Reactive Cassandra repositories can be implemented by using either RxJava or Project Reactor wrapper types by extending from one of the library-specific repository interfaces:
|
||||
|
||||
* `ReactiveCrudRepository`
|
||||
* `ReactiveSortingRepository`
|
||||
@@ -38,12 +34,11 @@ or Project Reactor wrapper types by extending from one of the library-specific r
|
||||
|
||||
Spring Data converts reactive wrapper types behind the scenes so that you can stick to your favorite composition library.
|
||||
|
||||
|
||||
[[cassandra.reactive.repositories.usage]]
|
||||
== Usage
|
||||
|
||||
To access domain entities stored in Apache Cassandra, you can use Spring Data's sophisticated repository support,
|
||||
which significantly eases implementing DAOs. To do so, create an interface for your repository, as the following example shows:
|
||||
To access domain entities stored in Apache Cassandra, you can use Spring Data's sophisticated repository support, which significantly eases implementing DAOs.
|
||||
To do so, create an interface for your repository, as the following example shows:
|
||||
|
||||
.Sample Person entity
|
||||
====
|
||||
@@ -63,8 +58,7 @@ public class Person {
|
||||
====
|
||||
|
||||
Note that the entity has a property named `id` of type `String`.
|
||||
The default serialization mechanism used in `CassandraTemplate` (which backs the repository support)
|
||||
regards properties named `id` as being the row ID.
|
||||
The default serialization mechanism used in `CassandraTemplate` (which backs the repository support) regards properties named `id` as being the row ID.
|
||||
|
||||
The following example shows a repository definition to persist `Person` entities:
|
||||
|
||||
@@ -86,16 +80,20 @@ public interface ReactivePersonRepository extends ReactiveSortingRepository<Pers
|
||||
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`.
|
||||
<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.
|
||||
<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.
|
||||
====
|
||||
|
||||
For Java configuration, use the `@EnableReactiveCassandraRepositories` annotation. The annotation carries the same attributes
|
||||
as the corresponding XML namespace element. If no base package is configured, the infrastructure scans the package
|
||||
of the annotated configuration class. The following example uses the `@EnableReactiveCassandraRepositories` annotation:
|
||||
For Java configuration, use the `@EnableReactiveCassandraRepositories` annotation.
|
||||
The annotation carries the same attributes as the corresponding XML namespace element.
|
||||
If no base package is configured, the infrastructure scans the package of the annotated configuration class.
|
||||
The following example uses the `@EnableReactiveCassandraRepositories` annotation:
|
||||
|
||||
.Java configuration for repositories
|
||||
====
|
||||
@@ -117,9 +115,8 @@ class ApplicationConfig extends AbstractReactiveCassandraConfiguration {
|
||||
----
|
||||
====
|
||||
|
||||
Since our domain repository extends `ReactiveSortingRepository`, it provides you with CRUD operations
|
||||
as well as methods for sorted access to the entities. Working with the repository instance is a matter of
|
||||
dependency injecting it into a client, as the following example shows:
|
||||
Since our domain repository extends `ReactiveSortingRepository`, it provides you with CRUD operations as well as methods for sorted access to the entities.
|
||||
Working with the repository instance is a matter of dependency injecting it into a client, as the following example shows:
|
||||
|
||||
.Sorted access to Person entities
|
||||
====
|
||||
@@ -137,7 +134,10 @@ public class PersonRepositoryTests {
|
||||
----
|
||||
====
|
||||
|
||||
Cassandra repositories support paging and sorting for paginated and sorted access to the entities. Cassandra paging requires a paging state to forward-only navigate through pages. A `Slice` keeps track of the current paging state and allows for creation of a `Pageable` to request the next page. The following example shows how to set up paging access to `Person` entities:
|
||||
Cassandra repositories support paging and sorting for paginated and sorted access to the entities.
|
||||
Cassandra paging requires a paging state to forward-only navigate through pages.
|
||||
A `Slice` keeps track of the current paging state and allows for creation of a `Pageable` to request the next page.
|
||||
The following example shows how to set up paging access to `Person` entities:
|
||||
|
||||
.Paging access to `Person` entities
|
||||
====
|
||||
@@ -162,19 +162,19 @@ public class PersonRepositoryTests {
|
||||
----
|
||||
====
|
||||
|
||||
The preceding example creates an application context with Spring's unit test support, which performs annotation-based
|
||||
dependency injection into the test class. Inside the test cases (the test methods), we use the repository to query
|
||||
the data store. We invoke the repository query method that requests all `Person` instances.
|
||||
The preceding example creates an application context with Spring's unit test support, which performs annotation-based dependency injection into the test class.
|
||||
Inside the test cases (the test methods), we use the repository to query the data store.
|
||||
We invoke the repository query method that requests all `Person` instances.
|
||||
|
||||
[[cassandra.reactive.repositories.features]]
|
||||
== Features
|
||||
|
||||
Spring Data's Reactive Cassandra support comes with the same set of features as
|
||||
the support for <<cassandra.repositories,imperative repositories>>.
|
||||
Spring Data's Reactive Cassandra support comes with the same set of features as the support for <<cassandra.repositories,imperative repositories>>.
|
||||
|
||||
It supports the following features:
|
||||
|
||||
* Query Methods that use <<cassandra.repositories.queries,String queries and Query Derivation>>
|
||||
* <<projections>>
|
||||
|
||||
NOTE: Query methods must return a reactive type. Resolved types (`User` versus `Mono<User>`) are not supported.
|
||||
NOTE: Query methods must return a reactive type.
|
||||
Resolved types (`User` versus `Mono<User>`) are not supported.
|
||||
|
||||
@@ -5,32 +5,30 @@ The reactive Cassandra support contains a wide range of features:
|
||||
|
||||
* Spring configuration support using Java-based `@Configuration` classes.
|
||||
* `ReactiveCqlTemplate` helper class that increases productivity by properly handling common Cassandra data access operations.
|
||||
* `ReactiveCassandraTemplate` helper class that increases productivity by using `ReactiveCassandraOperations` in a reactive manner. It includes integrated object mapping between tables and POJOs.
|
||||
* `ReactiveCassandraTemplate` helper class that increases productivity by using `ReactiveCassandraOperations` in a reactive manner.
|
||||
It includes integrated object mapping between tables and POJOs.
|
||||
* Exception translation into Spring's portable {spring-framework-docs}data-access.html#dao-exceptions[Data Access Exception Hierarchy].
|
||||
* Feature rich object mapping integrated with Spring's {spring-framework-docs}core.html#core-convert[Conversion Service].
|
||||
* Java-based Query, Criteria, and Update DSLs.
|
||||
* Automatic implementation of `Repository` interfaces, including support for custom finder methods.
|
||||
|
||||
For most data-oriented tasks, you can use the `ReactiveCassandraTemplate` or the repository support, which use
|
||||
the rich object mapping functionality. `ReactiveCqlTemplate` is commonly used to increment counters or perform ad-hoc
|
||||
CRUD operations. `ReactiveCqlTemplate` also provides callback methods that make it easy to get low-level
|
||||
API objects, such as `com.datastax.oss.driver.api.core.CqlSession`, which let you communicate directly with Cassandra.
|
||||
Spring Data for Apache Cassandra uses consistent naming conventions on objects in various APIs to those found
|
||||
in the DataStax Java Driver so that they are immediately familiar and so that you can map your existing knowledge
|
||||
onto the Spring APIs.
|
||||
For most data-oriented tasks, you can use the `ReactiveCassandraTemplate` or the repository support, which use the rich object mapping functionality. `ReactiveCqlTemplate` is commonly used to increment counters or perform ad-hoc CRUD operations. `ReactiveCqlTemplate` also provides callback methods that make it easy to get low-level API objects, such as `com.datastax.oss.driver.api.core.CqlSession`, which let you communicate directly with Cassandra.
|
||||
Spring Data for Apache Cassandra uses consistent naming conventions on objects in various APIs to those found in the DataStax Java Driver so that they are immediately familiar and so that you can map your existing knowledge onto the Spring APIs.
|
||||
|
||||
[[cassandra.reactive.getting-started]]
|
||||
== Getting Started
|
||||
|
||||
Spring Data for Apache Cassandra requires Apache Cassandra 2.1 or later and Datastax Java Driver 3.0 or later. An easy way to quickly set up and bootstrap a working environment is to create a Spring-based project in https://spring.io/tools/sts[STS] or use https://start.spring.io/[Spring Initializer].
|
||||
Spring Data for Apache Cassandra requires Apache Cassandra 2.1 or later and Datastax Java Driver 3.0 or later.
|
||||
An easy way to quickly set up and bootstrap a working environment is to create a Spring-based project in https://spring.io/tools/sts[STS] or use https://start.spring.io/[Spring Initializer].
|
||||
|
||||
First, you need to set up a running Apache Cassandra server. See the
|
||||
First, you need to set up a running Apache Cassandra server.
|
||||
See the
|
||||
https://cassandra.apache.org/doc/latest/getting_started/index.html[Apache Cassandra Quick Start Guide]
|
||||
for an explanation on how to start Apache Cassandra. Once installed, starting Cassandra is typically a matter of
|
||||
executing the following command: `CASSANDRA_HOME/bin/cassandra -f`.
|
||||
for an explanation on how to start Apache Cassandra.
|
||||
Once installed, starting Cassandra is typically a matter of executing the following command: `CASSANDRA_HOME/bin/cassandra -f`.
|
||||
|
||||
To create a Spring project in STS, go to File -> New -> Spring Template Project -> Simple Spring Utility Project
|
||||
and press Yes when prompted. Then enter a project and a package name, such as `org.spring.data.cassandra.example`.
|
||||
To create a Spring project in STS, go to File -> New -> Spring Template Project -> Simple Spring Utility Project and press Yes when prompted.
|
||||
Then enter a project and a package name, such as `org.spring.data.cassandra.example`.
|
||||
|
||||
Then you can add the following dependency declaration to your pom.xml file's `dependencies` section.
|
||||
|
||||
@@ -58,8 +56,7 @@ Also, you should change the version of Spring in the pom.xml file to be as follo
|
||||
----
|
||||
====
|
||||
|
||||
If using a milestone release instead of a GA release, you also need to add the location of the Spring Milestone
|
||||
repository for Maven to your pom.xml file so that it is at the same level of your `<dependencies/>` element, as follows:
|
||||
If using a milestone release instead of a GA release, you also need to add the location of the Spring Milestone repository for Maven to your pom.xml file so that it is at the same level of your `<dependencies/>` element, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -98,8 +95,7 @@ include::../{example-root}/ReactiveCassandraApplication.java[tags=file]
|
||||
|
||||
Even in this simple example, there are a few notable things to point out:
|
||||
|
||||
* A fully synchronous flow does not benefit from a reactive infrastructure, because a reactive programming model
|
||||
requires synchronization.
|
||||
* A fully synchronous flow does not benefit from a reactive infrastructure, because a reactive programming model requires synchronization.
|
||||
* You can create an instance of `ReactiveCassandraTemplate` with a Cassandra `CqlSession`.
|
||||
* You must annotate your POJO as a Cassandra `@Table` and annotate the `@PrimaryKey`.
|
||||
Optionally, you can override these mapping names to match your Cassandra database table and column names.
|
||||
@@ -108,35 +104,32 @@ Optionally, you can override these mapping names to match your Cassandra databas
|
||||
[[cassandra.reactive.examples-repo]]
|
||||
== Examples Repository
|
||||
|
||||
A https://github.com/spring-projects/spring-data-examples[Github repository] contains several examples that you
|
||||
can download and play around with to get a feel for how the library works.
|
||||
A https://github.com/spring-projects/spring-data-examples[Github repository] contains several examples that you can download and play around with to get a feel for how the library works.
|
||||
|
||||
[[cassandra.reactive.connectors]]
|
||||
== Connecting to Cassandra with Spring
|
||||
|
||||
One of the first tasks when using Apache Cassandra with Spring is to create a `com.datastax.oss.driver.api.core.CqlSession` object by
|
||||
using the Spring IoC container. You can do so either by using Java-based bean metadata or by using XML-based
|
||||
bean metadata. These are discussed in the following sections.
|
||||
One of the first tasks when using Apache Cassandra with Spring is to create a `com.datastax.oss.driver.api.core.CqlSession` object by using the Spring IoC container.
|
||||
You can do so either by using Java-based bean metadata or by using XML-based bean metadata.
|
||||
These are discussed in the following sections.
|
||||
|
||||
NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of
|
||||
XML-based metadata, see the high-level introduction in the reference docs
|
||||
NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs
|
||||
https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.0.html#new-java-configuration[here]
|
||||
as well as the detailed documentation {spring-framework-docs}core.html#beans-java-instantiating-container[here].
|
||||
|
||||
|
||||
[[reactive.cassandra.java-config]]
|
||||
=== Registering a Session instance using Java-based metadata
|
||||
|
||||
You can configure Reactive Cassandra support by using <<cassandra.cassandra-java-config,Java Configuration classes>>.
|
||||
Reactive Cassandra support adapts a `CqlSession` to provide a reactive execution model on top of an asynchronous driver.
|
||||
|
||||
A reactive `CqlSession` is configured similarly to an imperative `CqlSession`. We provide supporting configuration classes
|
||||
that come with predefined defaults and require only environment-specific information to configure Spring Data for
|
||||
Apache Cassandra. The base class for reactive support is `AbstractReactiveCassandraConfiguration`. This configuration
|
||||
class extends the imperative `AbstractCassandraConfiguration`, so the reactive support also configures
|
||||
the imperative API support. The following example shows how to register Apache Cassandra beans in a configuration class:
|
||||
ReactiveAppCassandraConfiguration
|
||||
.Registering Spring Data for Apache Cassandra beans using `AbstractReactiveCassandraConfiguration`
|
||||
A reactive `CqlSession` is configured similarly to an imperative `CqlSession`.
|
||||
We provide supporting configuration classes that come with predefined defaults and require only environment-specific information to configure Spring Data for Apache Cassandra.
|
||||
The base class for reactive support is `AbstractReactiveCassandraConfiguration`.
|
||||
This configuration class extends the imperative `AbstractCassandraConfiguration`, so the reactive support also configures the imperative API support.
|
||||
The following example shows how to register Apache Cassandra beans in a configuration class:
|
||||
ReactiveAppCassandraConfiguration .Registering Spring Data for Apache Cassandra beans using `AbstractReactiveCassandraConfiguration`
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@@ -150,35 +143,32 @@ See <<cassandra.schema-management>> for further details.
|
||||
[[cassandra.reactive.cql-template]]
|
||||
== `ReactiveCqlTemplate`
|
||||
|
||||
The `ReactiveCqlTemplate` class is the central class in the core CQL package. It handles the creation and release
|
||||
of resources. It performs the basic tasks of the core CQL workflow, such as statement creation and execution,
|
||||
leaving application code to provide CQL and extract results. The `ReactiveCqlTemplate` class executes CQL queries
|
||||
and update statements and performs iteration over `ResultSet` instances and extraction of returned parameter values.
|
||||
It also catches CQL exceptions and translates them into the generic, more informative, exception hierarchy defined in
|
||||
the `org.springframework.dao` package.
|
||||
The `ReactiveCqlTemplate` class is the central class in the core CQL package.
|
||||
It handles the creation and release of resources.
|
||||
It performs the basic tasks of the core CQL workflow, such as statement creation and execution, leaving application code to provide CQL and extract results.
|
||||
The `ReactiveCqlTemplate` class executes CQL queries and update statements and performs iteration over `ResultSet` instances and extraction of returned parameter values.
|
||||
It also catches CQL exceptions and translates them into the generic, more informative, exception hierarchy defined in the `org.springframework.dao` package.
|
||||
|
||||
When you use the `ReactiveCqlTemplate` in your code, you need only implement callback interfaces, which have a
|
||||
clearly defined contract. Given a `Connection`, the `ReactivePreparedStatementCreator` callback interface
|
||||
creates a prepared statement with the provided CQL and any necessary parameter arguments. The `RowCallbackHandler`
|
||||
When you use the `ReactiveCqlTemplate` in your code, you need only implement callback interfaces, which have a clearly defined contract.
|
||||
Given a `Connection`, the `ReactivePreparedStatementCreator` callback interface creates a prepared statement with the provided CQL and any necessary parameter arguments.
|
||||
The `RowCallbackHandler`
|
||||
interface extracts values from each row of a `ReactiveResultSet`.
|
||||
|
||||
The `ReactiveCqlTemplate` can be used within a DAO implementation through direct instantiation with a `ReactiveSessionFactory`
|
||||
reference or be configured in the Spring container and given to DAOs as a bean reference. `ReactiveCqlTemplate` is
|
||||
a foundational building block for <<cassandra.reactive.template,`ReactiveCassandraTemplate`>>.
|
||||
|
||||
All CQL issued by this class is logged at the `DEBUG` level under the category corresponding to the fully-qualified
|
||||
class name of the template instance (typically `ReactiveCqlTemplate`, but it may be different if you use
|
||||
a custom subclass of the `ReactiveCqlTemplate` class).
|
||||
reference or be configured in the Spring container and given to DAOs as a bean reference. `ReactiveCqlTemplate` is a foundational building block for <<cassandra.reactive.template,`ReactiveCassandraTemplate`>>.
|
||||
|
||||
All CQL issued by this class is logged at the `DEBUG` level under the category corresponding to the fully-qualified class name of the template instance (typically `ReactiveCqlTemplate`, but it may be different if you use a custom subclass of the `ReactiveCqlTemplate` class).
|
||||
|
||||
[[cassandra.reactive.cql-template.examples]]
|
||||
=== Examples of `ReactiveCqlTemplate` Class Usage
|
||||
|
||||
This section provides some examples of `ReactiveCqlTemplate` class usage. These examples are not an exhaustive list
|
||||
of all of the functionality exposed by the `ReactiveCqlTemplate`. See the attendant https://docs.spring.io/spring-data/cassandra/docs/{version}/api/org/springframework/data/cassandra/core/cql/ReactiveCqlTemplate.html[Javadocs] for that.
|
||||
This section provides some examples of `ReactiveCqlTemplate` class usage.
|
||||
These examples are not an exhaustive list of all of the functionality exposed by the `ReactiveCqlTemplate`.
|
||||
See the attendant https://docs.spring.io/spring-data/cassandra/docs/{version}/api/org/springframework/data/cassandra/core/cql/ReactiveCqlTemplate.html[Javadocs] for that.
|
||||
|
||||
[[cql-template.examples.query]]
|
||||
==== Querying (SELECT) with `ReactiveCqlTemplate`
|
||||
|
||||
The following query gets the number of rows in a relation:
|
||||
|
||||
====
|
||||
@@ -224,9 +214,7 @@ include::../{example-root}/ReactiveCqlTemplateExamples.java[tags=listOfRowMapper
|
||||
----
|
||||
====
|
||||
|
||||
If the last two snippets of code actually existed in the same application, it would make sense to remove the
|
||||
duplication present in the two `RowMapper` anonymous inner classes and extract them into a single class
|
||||
(typically a `static` nested class) that can then be referenced by DAO methods as needed.
|
||||
If the last two snippets of code actually existed in the same application, it would make sense to remove the duplication present in the two `RowMapper` anonymous inner classes and extract them into a single class (typically a `static` nested class) that can then be referenced by DAO methods as needed.
|
||||
|
||||
For example, it might be better to write the last code snippet as follows:
|
||||
|
||||
@@ -240,8 +228,8 @@ include::../{example-root}/ReactiveCqlTemplateExamples.java[tags=findAllActors]
|
||||
[[cassandra.reactive.cql-template.examples.update]]
|
||||
==== `INSERT`, `UPDATE`, and `DELETE` with `ReactiveCqlTemplate`
|
||||
|
||||
You can use the `execute(…)` method to perform `INSERT`, `UPDATE`, and `DELETE` operations. Parameter values are usually provided
|
||||
as variable arguments or, alternatively, as an object array.
|
||||
You can use the `execute(…)` method to perform `INSERT`, `UPDATE`, and `DELETE` operations.
|
||||
Parameter values are usually provided as variable arguments or, alternatively, as an object array.
|
||||
|
||||
The following example shows how to perform an `INSERT` operation with `ReactiveCqlTemplate`:
|
||||
|
||||
@@ -272,53 +260,45 @@ include::../{example-root}/ReactiveCqlTemplateExamples.java[tags=delete]
|
||||
|
||||
include::exception-translation.adoc[]
|
||||
|
||||
`ReactiveCqlTemplate` and `ReactiveCassandraTemplate` propagate exceptions as early as possible. Exceptions that occur
|
||||
during execution of the reactive sequence are emitted as error signals.
|
||||
|
||||
`ReactiveCqlTemplate` and `ReactiveCassandraTemplate` propagate exceptions as early as possible.
|
||||
Exceptions that occur during execution of the reactive sequence are emitted as error signals.
|
||||
|
||||
[[cassandra.reactive.template]]
|
||||
== Introduction to `ReactiveCassandraTemplate`
|
||||
|
||||
The `ReactiveCassandraTemplate` class, located in the `org.springframework.data.cassandra` package, is the central class
|
||||
in Spring Data's Cassandra support. It provides a rich feature set to interact with the database. The template offers
|
||||
convenience data access operations to create, update, delete, and query Cassandra and provides a mapping between
|
||||
your domain objects and Cassandra table rows.
|
||||
The `ReactiveCassandraTemplate` class, located in the `org.springframework.data.cassandra` package, is the central class in Spring Data's Cassandra support.
|
||||
It provides a rich feature set to interact with the database.
|
||||
The template offers convenience data access operations to create, update, delete, and query Cassandra and provides a mapping between your domain objects and Cassandra table rows.
|
||||
|
||||
NOTE: Once configured, `ReactiveCassandraTemplate` is thread-safe and can be reused across multiple instances.
|
||||
|
||||
The mapping between rows in a Cassandra table and domain classes is done by delegating to an implementation of
|
||||
the `CassandraConverter` interface. Spring provides a default implementation, `MappingCassandraConverter`,
|
||||
but you can also write your own custom converter. See "`<<mapping.chapter>>`"
|
||||
for more detailed information.
|
||||
The mapping between rows in a Cassandra table and domain classes is done by delegating to an implementation of the `CassandraConverter` interface.
|
||||
Spring provides a default implementation, `MappingCassandraConverter`, but you can also write your own custom converter.
|
||||
See "`<<mapping.chapter>>`" for more detailed information.
|
||||
|
||||
The `ReactiveCassandraTemplate` class implements the `ReactiveCassandraOperations` interface. As often as possible,
|
||||
the methods names `ReactiveCassandraOperations` match names in Cassandra to make the API familiar
|
||||
to developers who are familiar with Cassandra.
|
||||
The `ReactiveCassandraTemplate` class implements the `ReactiveCassandraOperations` interface.
|
||||
As often as possible, the methods names `ReactiveCassandraOperations` match names in Cassandra to make the API familiar to developers who are familiar with Cassandra.
|
||||
|
||||
For example, you can find methods such as `select`, `insert`, `delete`, and `update`. The design goal was to make it
|
||||
as easy as possible to transition between the use of the base Cassandra driver and `ReactiveCassandraOperations`.
|
||||
A major difference between the two APIs is that `ReactiveCassandraOperations` can be passed domain objects instead of
|
||||
CQL and query objects.
|
||||
For example, you can find methods such as `select`, `insert`, `delete`, and `update`.
|
||||
The design goal was to make it as easy as possible to transition between the use of the base Cassandra driver and `ReactiveCassandraOperations`.
|
||||
A major difference between the two APIs is that `ReactiveCassandraOperations` can be passed domain objects instead of CQL and query objects.
|
||||
|
||||
NOTE: The preferred way to reference operations on a `ReactiveCassandraTemplate` instance is through its interface,
|
||||
`ReactiveCassandraOperations`.
|
||||
|
||||
The default converter implementation for `ReactiveCassandraTemplate` is `MappingCassandraConverter`.
|
||||
While the `MappingCassandraConverter` can make use of additional metadata to specify the mapping of objects to rows,
|
||||
it can also convert objects that contain no additional metadata by using conventions for the mapping of
|
||||
fields and table names. These conventions, as well as the use of mapping annotations, are explained in
|
||||
"`<<mapping.chapter>>`".
|
||||
While the `MappingCassandraConverter` can make use of additional metadata to specify the mapping of objects to rows, it can also convert objects that contain no additional metadata by using conventions for the mapping of fields and table names.
|
||||
These conventions, as well as the use of mapping annotations, are explained in "`<<mapping.chapter>>`".
|
||||
|
||||
Another central feature of `CassandraTemplate` is exception translation. Exceptions thrown by the Cassandra
|
||||
Java driver are translated into Spring's portable Data Access Exception hierarchy. See
|
||||
"`<<cassandra.exception>>`" for more information.
|
||||
Another central feature of `CassandraTemplate` is exception translation.
|
||||
Exceptions thrown by the Cassandra Java driver are translated into Spring's portable Data Access Exception hierarchy.
|
||||
See "`<<cassandra.exception>>`" for more information.
|
||||
|
||||
[[cassandra.reactive.template.instantiating]]
|
||||
=== Instantiating `ReactiveCassandraTemplate`
|
||||
|
||||
`ReactiveCassandraTemplate` should always be configured as a Spring bean, although an earlier example showed
|
||||
how to instantiate it directly. However, this section assumes that the template is used in a Spring module, so it also assumes
|
||||
that the Spring container is being used.
|
||||
`ReactiveCassandraTemplate` should always be configured as a Spring bean, although an earlier example showed how to instantiate it directly.
|
||||
However, this section assumes that the template is used in a Spring module, so it also assumes that the Spring container is being used.
|
||||
|
||||
There are two ways to get a `ReactiveCassandraTemplate`, depending on how you load you Spring `ApplicationContext`:
|
||||
|
||||
@@ -340,8 +320,7 @@ private ReactiveCassandraOperations reactiveCassandraOperations;
|
||||
====
|
||||
|
||||
Like all Spring autowiring, this assumes there is only one bean of type `ReactiveCassandraOperations` in the `ApplicationContext`.
|
||||
If you have multiple `ReactiveCassandraTemplate` beans (which can be the case if you are working with multiple keyspaces
|
||||
in the same project), then you can use the `@Qualifier` annotation to designate which bean you want to autowire.
|
||||
If you have multiple `ReactiveCassandraTemplate` beans (which can be the case if you are working with multiple keyspaces in the same project), then you can use the `@Qualifier` annotation to designate which bean you want to autowire.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -368,23 +347,22 @@ ReactiveCassandraOperations reactiveCassandraOperations = applicationContext.get
|
||||
[[cassandra.reactive.template.save-update-remove]]
|
||||
== Saving, Updating, and Removing Rows
|
||||
|
||||
`ReactiveCassandraTemplate` provides a simple way for you to save, update, and delete your domain objects
|
||||
and map those objects to tables managed in Cassandra.
|
||||
`ReactiveCassandraTemplate` provides a simple way for you to save, update, and delete your domain objects and map those objects to tables managed in Cassandra.
|
||||
|
||||
[[cassandra.reactive.template.insert-update]]
|
||||
=== Methods for Inserting and Updating rows
|
||||
|
||||
`CassandraTemplate` has several convenient methods for saving and inserting your objects. To have more
|
||||
fine-grained control over the conversion process, you can register Spring `Converter` instances with the `MappingCassandraConverter`
|
||||
`CassandraTemplate` has several convenient methods for saving and inserting your objects.
|
||||
To have more fine-grained control over the conversion process, you can register Spring `Converter` instances with the `MappingCassandraConverter`
|
||||
(for example, `Converter<Row, Person>`).
|
||||
|
||||
NOTE: The difference between insert and update operations is that `INSERT` operations do not insert `null` values.
|
||||
|
||||
The simple case of using the `INSERT` operation is to save a POJO. In this case, the table name is determined by
|
||||
the simple class name (not the fully qualified class name). The table to store the object can be overridden by
|
||||
using mapping metadata.
|
||||
The simple case of using the `INSERT` operation is to save a POJO. In this case, the table name is determined by the simple class name (not the fully qualified class name).
|
||||
The table to store the object can be overridden by using mapping metadata.
|
||||
|
||||
When inserting or updating, the `id` property must be set. Apache Cassandra has no means to generate an ID.
|
||||
When inserting or updating, the `id` property must be set.
|
||||
Apache Cassandra has no means to generate an ID.
|
||||
|
||||
The following example uses the save operation and retrieves its contents:
|
||||
|
||||
@@ -406,14 +384,12 @@ Mono<Person> queriedBob = reactiveCassandraTemplate.selectOneById(query(where("a
|
||||
You can use the following operations to insert and save:
|
||||
|
||||
* `void` *insert* `(Object objectToSave)`: Inserts the object in an Apache Cassandra table.
|
||||
* `WriteResult` *insert* `(Object objectToSave, InsertOptions options)`: Inserts the object in an Apache Cassandra table and
|
||||
applies `InsertOptions`.
|
||||
* `WriteResult` *insert* `(Object objectToSave, InsertOptions options)`: Inserts the object in an Apache Cassandra table and applies `InsertOptions`.
|
||||
|
||||
You can use the following update operations:
|
||||
|
||||
* `void` *update* `(Object objectToSave)`: Updates the object in an Apache Cassandra table.
|
||||
* `WriteResult` *update* `(Object objectToSave, UpdateOptions options)`: Updates the object in an Apache Cassandra table and
|
||||
applies `UpdateOptions`.
|
||||
* `WriteResult` *update* `(Object objectToSave, UpdateOptions options)`: Updates the object in an Apache Cassandra table and applies `UpdateOptions`.
|
||||
|
||||
You can also use the old fashioned way and write your own CQL statements, as the following example shows:
|
||||
|
||||
@@ -424,25 +400,22 @@ String cql = "INSERT INTO person (age, name) VALUES (39, 'Bob')";
|
||||
Mono<Boolean> applied = reactiveCassandraTemplate.getReactiveCqlOperations().execute(cql);
|
||||
----
|
||||
|
||||
You can also configure additional options such as TTL, consistency level, and lightweight transactions
|
||||
when using `InsertOptions` and `UpdateOptions`.
|
||||
You can also configure additional options such as TTL, consistency level, and lightweight transactions when using `InsertOptions` and `UpdateOptions`.
|
||||
|
||||
[[cassandra.reactive.template.insert-update.table]]
|
||||
==== Which Table Are My Rows Inserted into?
|
||||
|
||||
You can manage the table name that is used for operating on the tables in two ways. The default table name
|
||||
is the simple class name changed to start with a lower-case letter. So, an instance of
|
||||
the `com.example.Person` class would be stored in the `person` table.
|
||||
You can manage the table name that is used for operating on the tables in two ways.
|
||||
The default table name is the simple class name changed to start with a lower-case letter.
|
||||
So, an instance of the `com.example.Person` class would be stored in the `person` table.
|
||||
The second way is to specify a table name in the `@Table` annotation.
|
||||
|
||||
|
||||
[[cassandra.reactive.template.update]]
|
||||
=== Updating Rows in a Table
|
||||
|
||||
For updates, you can select to update a number of rows.
|
||||
|
||||
The following example shows updating a single account object by adding a one-time $50.00 bonus to the balance
|
||||
with the `+` assignment:
|
||||
The following example shows updating a single account object by adding a one-time $50.00 bonus to the balance with the `+` assignment:
|
||||
|
||||
.Updating rows using `ReactiveCasandraTemplate`
|
||||
====
|
||||
|
||||
Reference in New Issue
Block a user