[[cassandra.core]]
= Cassandra Support

Spring Data support for Apache Cassandra contains a wide range of features:

* Spring configuration support with Java-based `@Configuration` classes or the XML namespace.
* The `CqlTemplate` helper class that increases productivity by properly handling common Cassandra data access operations.
* The `CassandraTemplate` helper class that provides object mapping between CQL 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].
* Annotation-based mapping metadata that is extensible to support other metadata formats.
* 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.

[[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].

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`.

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.

====
[source,xml,subs="verbatim,attributes"]
----
<dependencies>

  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-cassandra</artifactId>
    <version>{version}</version>
  </dependency>

</dependencies>
----
====

Also, you should change the version of Spring in the pom.xml file to be as follows:

====
[source,xml,subs="verbatim,attributes"]
----
<spring.framework.version>{springVersion}</spring.framework.version>
----
====

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]
----
<repositories>
  <repository>
    <id>spring-milestone</id>
    <name>Spring Maven MILESTONE Repository</name>
    <url>https://repo.spring.io/libs-milestone</url>
  </repository>
</repositories>
----

The repository is also https://repo.spring.io/milestone/org/springframework/data/[browseable here].

You can also browse all Spring repositories https://repo.spring.io/webapp/#/home[here].

Now you can create a simple Java application that stores and reads a domain object to and from Cassandra.

To do so, first create a simple domain object class to persist, as the following example shows:

====
[source,java]
----
include::../{example-root}/Person.java[tags=file]
----
====

Next, create the main application to run, as the following example shows:

====
[source,java]
----
include::../{example-root}/CassandraApplication.java[tags=file]
----
====

Even in this simple example, there are a few notable things to point out:

* You can create an instance of `CassandraTemplate` with a Cassandra `CqlSession`.
* You must annotate your POJO as a Cassandra `@Table` entity and also annotate the `@PrimaryKey`.
Optionally, you can override these mapping names to match your Cassandra database table and column names.
* You can either use raw CQL or the DataStax `QueryBuilder` API to construct your queries.

[[cassandra.examples-repo]]
== Examples Repository

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.

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].

[[cassandra.cassandra-java-config]]
=== Registering a Session Instance by Using Java-based Metadata

The following example shows how to use Java-based bean metadata to register an instance of a `com.datastax.oss.driver.api.core.CqlSession`:

.Registering a `com.datastax.oss.driver.api.core.CqlSession` object by using Java-based bean metadata
====
[source,java]
----
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
`@Repository` is described in {spring-framework-docs}data-access.html[Spring's DAO support features].

The following example shows Java-based factory class usage:

.Registering a com.datastax.oss.driver.api.core.CqlSession object by using Spring's `CqlSessionFactoryBean`:
====
[source,java]
----
include::../{example-root}/FactoryBeanAppConfig.java[tags=class]
----
====

Using `CassandraTemplate` with object mapping and repository support requires a `CassandraTemplate`,
`CassandraMappingContext`, `CassandraConverter`, and enabling repository support.

The following example shows how to register components to configure object mapping and repository support:

.Registering components to configure object mapping and repository support
====
[source,java]
----
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
`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`:

.Registering Spring Data for Apache Cassandra beans by using `AbstractCassandraConfiguration`
====
[source,java]
----
include::../{example-root}/CassandraConfiguration.java[tags=class]
----
====

[[cassandra-connectors.xmlconfig]]
=== XML Configuration

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 required fields.

The following example shows our properties file, called `cassandra.properties`:

====
[source]
----
cassandra.contactpoints=10.1.55.80:9042,10.1.55.81:9042
cassandra.keyspace=showcase
----
====

In the next two examples, we use Spring to load these properties into the Spring context.

==== Registering a Session Instance by using XML-based Metadata

While you can use Spring's traditional `<beans/>` XML namespace to register an instance of
`com.datastax.oss.driver.api.core.CqlSession` with the container, the XML can be quite verbose, because it is general purpose.
XML namespaces are a better alternative to configuring commonly used objects, such as the `CqlSession` instance.
The `cassandra` namespace let you create a `CqlSession` instance.

The following example shows how to configure the `cassandra` namespace:

.XML schema to configure Cassandra by using the `cassandra` namespace
====
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
  xsi:schemaLocation="
    http://www.springframework.org/schema/data/cassandra
    https://www.springframework.org/schema/data/cassandra/spring-cassandra.xsd
    http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd">

  <!-- Default bean name is 'cassandraSession' -->
  <cassandra:session contact-points="localhost" port="9042">
    <cassandra:keyspace action="CREATE_DROP" name="mykeyspace" />
  </cassandra:session>

  <cassandra:session-factory>
    <cassandra:script
            location="classpath:/org/springframework/data/cassandra/config/schema.cql"/>
  </cassandra:session-factory>
</beans>
----
====

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

.Configuring Spring Data components by using XML
====
[source,xml]
----

<!-- Loads the properties into the Spring Context and uses them to fill
in placeholders in the bean definitions -->
<context:property-placeholder location="classpath:cassandra.properties" />

<!-- REQUIRED: The Cassandra Session -->
<cassandra:session contact-points="${cassandra.contactpoints}" keyspace-name="${cassandra.keyspace}" />

<!-- REQUIRED: The default Cassandra mapping context used by `CassandraConverter` -->
<cassandra:mapping>
  <cassandra:user-type-resolver keyspace-name="${cassandra.keyspace}" />
</cassandra:mapping>

<!-- REQUIRED: The default Cassandra converter used by `CassandraTemplate` -->
<cassandra:converter />

<!-- REQUIRED: The Cassandra template is the foundation of all Spring
Data Cassandra -->
<cassandra:template id="cassandraTemplate" />

<!-- OPTIONAL: If you use Spring Data for Apache Cassandra repositories, add
your base packages to scan here -->
<cassandra:repositories base-package="org.spring.cassandra.example.repo" />

----
====

[[cassandra.schema-management]]
== Schema Management

Apache Cassandra is a data store that requires a schema definition prior to any data interaction.
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.

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
====
[source,xml]
----
<cassandra:session>

    <cassandra:keyspace action="CREATE_DROP" durable-writes="true" name="my_keyspace">
        <cassandra:replication class="NETWORK_TOPOLOGY_STRATEGY">
          <cassandra:data-center name="foo" replication-factor="1" />
          <cassandra:data-center name="bar" replication-factor="2" />
        </cassandra:replication>
  </cassandra:keyspace>

</cassandra:session>
----
====

You can also specify a Cassandra keyspace by using Java configuration, as the following example shows:

.Specifying a Cassandra keyspace by using Java configuration
====
[source,java]
----
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.

[[cassandra.schema-management.initializing]]
=== Initializing a `SessionFactory`

The `org.springframework.data.cassandra.core.cql.session.init` package provides support for initializing an existing `SessionFactory`.
You may sometimes need to initialize a keyspace that runs on a server somewhere.

[[cassandra.schema-management.initializing.config]]
==== Initializing a Keyspace

You can provide arbitrary CQL that is executed on `CqlSession` initialization and shutdown in the configured keyspace, as the following Java configuration example shows:

====
[source,java]
----
include::../{example-root}/KeyspacePopulatorConfiguration.java[tags=class]
----
====

If you want to initialize a database using XML configuration and you can provide a reference to a `SessionFactory` bean, you can use the `initialize-keyspace` tag in the `cassandra` namespace:

====
[source,xml,indent=0,subs="verbatim,quotes"]
----
<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory">
    <cassandra:script location="classpath:com/foo/cql/db-schema.cql"/>
    <cassandra:script location="classpath:com/foo/cql/db-test-data.cql"/>
</cassandra:initialize-keyspace>
----
====

The preceding example runs the two specified scripts against the keyspace.
The first script creates a schema, and the second populates tables with a test data set.
The script locations can also be patterns with wildcards in the usual Ant style used for resources in Spring (for example, `classpath{asterisk}:/com/foo/{asterisk}{asterisk}/cql/{asterisk}-data.cql`).
If you use a pattern, the scripts are run in the lexical order of their URL or filename.

The default behavior of the keyspace initializer is to unconditionally run the provided scripts.
This may not always be what you want -- for instance, if you run the scripts against a keyspace that already has test data in it.
The likelihood of accidentally deleting data is reduced by following the common pattern (shown earlier) of creating the tables first and then inserting the data.
The first step fails if the tables already exist.

However, to gain more control over the creation and deletion of existing data, the XML namespace provides a few additional options.
The first is a flag to switch the initialization on and off.
You can set this according to the environment (such as pulling a boolean value from system properties or from an environment bean).
The following example gets a value from a system property:

====
[source,xml,indent=0,subs="verbatim,quotes"]
----
<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory"
    enabled="#{systemProperties.INITIALIZE_KEYSPACE}">    <1>
    <cassandra:script location="..."/>
</cassandra:initialize-database>
----
<1> Get the value for `enabled` from a system property called `INITIALIZE_KEYSPACE`.
====

The second option to control what happens with existing data is to be more tolerant of failures.
To this end, you can control the ability of the initializer to ignore certain errors in the CQL it executes from the scripts, as the following example shows:

====
[source,xml,indent=0,subs="verbatim,quotes"]
----
<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory" ignore-failures="DROPS">
    <cassandra:script location="..."/>
</cassandra:initialize-database>
----
====

In the preceding example, we are saying that we expect that, sometimes, the scripts are run against an empty keyspace, and there are some `DROP` statements in the scripts that would, therefore, fail.
So failed CQL `DROP` statements will be ignored, but other failures will cause an exception.
This is useful if you don't want tu use support `DROP ... IF EXISTS` (or similar) but you want to unconditionally remove all test data before re-creating it.
In that case the first script is usually a set of `DROP` statements, followed by a set of `CREATE` statements.

The `ignore-failures` option can be set to `NONE` (the default), `DROPS` (ignore failed drops), or `ALL` (ignore all failures).

Each statement should be separated by `;` or a new line if the `;` character is not present at all in the script.
You can control that globally or script by script, as the following example shows:

====
[source,java]
----
include::../{example-root}/SessionFactoryInitializerConfiguration.java[tags=class]
----
====

Alternatively, you can use XML to configure the `SessionFactoryInitializer`:

====
[source,xml,indent=0,subs="verbatim,quotes"]
----
<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory" separator="@@">        <1>
    <cassandra:script location="classpath:com/myapp/cql/db-schema.cql" separator=";"/>     <2>
    <cassandra:script location="classpath:com/myapp/cql/db-test-data-1.cql"/>
    <cassandra:script location="classpath:com/myapp/cql/db-test-data-2.cql"/>
</cassandra:initialize-keyspace>
----
<1> Set the separator scripts to `@@`.
<2> Set the separator for `db-schema.cql` to `;`.
====

In this example, the two `test-data` scripts use `@@` as statement separator and only the `db-schema.cql` uses `;`.
This configuration specifies that the default separator is `@@` and overrides that default for the `db-schema` script.

If you need more control than you get from the XML namespace, you can use the `SessionFactoryInitializer` directly and define it as a component in your application.

[[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.
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`).
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.

To get around this issue, you have two options: change your cache initialization strategy to a later phase or ensure that the keyspace initializer is initialized first.

Changing your cache initialization strategy might be easy if the application is in your control and not otherwise.
Some suggestions for how to implement this include:

* Make the cache initialize lazily on first usage, which improves application startup time.
* Have your cache or a separate component that initializes the cache implement `Lifecycle` or `SmartLifecycle`.
When the application context starts, you can automatically start a `SmartLifecycle` by setting its `autoStartup` flag, and you can manually start a `Lifecycle` by calling `ConfigurableApplicationContext.start()` on the enclosing context.
* Use a Spring `ApplicationEvent` or similar custom observer mechanism to trigger the cache initialization. `ContextRefreshedEvent` is always published by the context when it is ready for use (after all beans have been initialized), so that is often a useful hook (this is how the `SmartLifecycle` works by default).

Ensuring that the keyspace initializer is initialized first can also be easy.
Some suggestions on how to implement this include:

* Rely on the default behavior of the Spring `BeanFactory`, which is that beans are initialized in registration order.
You can easily arrange that by adopting the common practice of a set of `<import/>` elements in XML configuration that order your application modules and ensuring that the database and database initialization are listed first.
* Separate the `SessionFactory` and the business components that use it and control their startup order by putting them in separate `ApplicationContext` instances (for example, the parent context contains the `SessionFactory`, and the child context contains the business components).
This structure is common in Spring web applications but can be more generally applied.
* Use the Schema management for <<cassandra.schema-management.tables>> to initialize the keyspace using Spring Data Cassandra's built-in schema generator.

[[cassandra.schema-management.tables]]
=== Tables and User-defined Types

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:

* `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.
`RECREATE_DROP_UNUSED` also drops tables and types that are not known to the application.

==== 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 = …)`
to specify the desired column type.

The following example shows how to specify entity base packages in XML configuration:

.Specifying entity base packages with XML configuration
====
[source,xml]
----

<cassandra:mapping entity-base-packages="com.foo,com.bar"/>

----
====

The following example shows how to specify entity base packages in Java configuration:

.Specifying entity base packages with Java configuration
====
[source,java]
----
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.

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 <<cassandra.template.prepared-statements.cql,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`>>.

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.

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.

[[cassandra.cql-template.examples.query]]
==== Querying (SELECT) with `CqlTemplate`

The following query gets the number of rows in a table:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=rowCount]
----
====

The following query uses a bind variable:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=countOfActorsNamedJoe]
----
====

The following example queries for a `String`:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=lastName]
----
====

The following example queries and populates a single domain object:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=rowMapper]
----
====

The following example queries and populates multiple domain objects:

====
[source,java,indent=0]
----
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.

For example, it might be better to write the last code snippet as follows:

====
[source,java,indent=0]
----
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.

The following example shows how to perform an `INSERT` operation with `CqlTemplate`:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=insert]
----
====

The following example shows how to perform an `UPDATE` operation with `CqlTemplate`:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=update]
----
====

The following example shows how to perform an `DELETE` operation with `CqlTemplate`:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=delete]
----
====

[[cassandra.cql-template.examples.other]]
==== Other `CqlTemplate` operations

You can use the `execute(..)` method to execute any arbitrary CQL. As a result, the method is often used for DDL statements.
It is heavily overloaded with variants that take callback interfaces, bind variable arrays, and so on.

The following example shows how to create and drop a table by using different API objects that are all passed to the `execute()` methods:

====
[source,java]
----
include::../{example-root}/CqlTemplateExamples.java[tags=other]
----
====

[[cassandra.exception]]
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.
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.
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`:

[source,java]
----
Session session = … // get a Cassandra Session

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.

You can find various `SessionFactory` implementations within the `org.springframework.data.cassandra.core.cql.session`
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.

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
<<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.

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>>.

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.

[[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.

There are two ways to get a `CassandraTemplate`, depending on how you load you Spring `ApplicationContext`:

* <<cassandra-template-autowiring>>
* <<cassandra-template-bean-lookup-applicationcontext>>

[float]
[[cassandra-template-autowiring]]
==== Autowiring

You can autowire a `CassandraOperations` into your project, as the following example shows:

====
[source,java]
----
@Autowired
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.

====
[source,java]
----
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private CassandraOperations cassandraOperations;
----
====

[float]
[[cassandra-template-bean-lookup-applicationcontext]]
==== Bean Lookup with `ApplicationContext`

You can also look up the `CassandraTemplate` bean from the `ApplicationContext`, as shown in the following example:

====
[source,java]
----
CassandraOperations cassandraOperations = applicationContext.getBean("cassandraTemplate", CassandraOperations.class);
----
====

[[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.

[[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.
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`
(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.

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:

.Inserting and retrieving objects by using the `CassandraTemplate`
====
[source,java]
----
import static org.springframework.data.cassandra.core.query.Criteria.where;
import static org.springframework.data.cassandra.core.query.Query.query;
…

Person bob = new Person("Bob", 33);
cassandraTemplate.insert(bob);

Person queriedBob = cassandraTemplate.selectOneById(query(where("age").is(33)), Person.class);
----
====

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`.

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`.

You can also use the old fashioned way and write your own CQL statements, as the following example shows:

[source,java]
----
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`.

[[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.
The second way is to specify a table name in the `@Table` annotation.

[[cassandra.template.batch]]
==== Inserting, Updating, and Deleting Individual Objects in a Batch

The Cassandra protocol supports inserting a collection of rows in one operation by using a batch.

The following methods in the `CassandraTemplate` interface support this functionality:

* `batchOps`: Creates a new `CassandraBatchOperations` to populate the batch.

`CassandraBatchOperations`

* `insert`: Takes a single object, an array (var-args), or an `Iterable` of objects to insert.
* `update`: Takes a single object, an array (var-args), or an `Iterable` of objects to update.
* `delete`: Takes a single object, an array (var-args), or an `Iterable` of objects to delete.
* `withTimestamp`: Applies a TTL to the batch.
* `execute`: Executes the batch.

[[cassandra.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:

.Updating rows using `CasandraTemplate`
====
[source,java]
----
import static org.springframework.data.cassandra.core.query.Criteria.where;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;

…

boolean applied = cassandraTemplate.update(Query.query(where("id").is("foo")),
  Update.create().increment("balance", 50.00), Account.class);
----
====

In addition to the `Query` discussed earlier, we provide the update definition by using an `Update` object.
The `Update` class has methods that match the update assignments available for Apache Cassandra.

Most methods return the `Update` object to provide a fluent API for code styling purposes.

[[cassandra.template.update.methods]]
==== Methods for Executing Updates for Rows

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.

[[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.

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 `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... 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 `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.
* `Update` *increment* `(String columnName, Number delta)`: Updates by using the `+` update assignment.
* `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.

The following listing shows a few update examples:

====
[source]
----
// UPDATE … SET key = 'Spring Data';
Update.update("key", "Spring Data")

// UPDATE … SET key[5] = 'Spring Data';
Update.empty().set("key").atIndex(5).to("Spring Data");

// UPDATE … SET key = key + ['Spring', 'DATA'];
Update.empty().addTo("key").appendAll("Spring", "Data");
----
====

Note that `Update` is immutable once created.
Invoking methods creates new immutable (intermediate) `Update` objects.

[[cassandra.template.delete]]
=== Methods for Removing Rows

You can use the following overloaded methods to remove an object from the database:

* `boolean` *delete* `(Query query, Class<?> entityClass)`: Deletes the objects selected by `Query`.
* `T` *delete* `(T entity)`: Deletes the given object.
* `T` *delete* `(T entity, QueryOptions queryOptions)`: Deletes the given object applying `QueryOptions`.
* `boolean` *deleteById* `(Object id, Class<?> entityClass)`: Deletes the object using the given Id.

[[cassandra.template.optimistic-locking]]
=== Optimistic Locking

The `@Version` annotation provides syntax similar to that of JPA in the context of Cassandra and makes sure updates are only applied to rows with a matching version.
Optimistic Locking leverages Cassandra's lightweight transactions to conditionally insert, update and delete rows.
Therefore, `INSERT` statements are executed with the `IF NOT EXISTS` condition.
For updates and deletes, the actual value of the version property is added to the `UPDATE` condition in such a way that the modification does not have any effect if another operation altered the row in the meantime.
In that case, an `OptimisticLockingFailureException` is thrown.
The following example shows these features:

====
[source,java]
----
@Table
class Person {

  @Id String id;
  String firstname;
  String lastname;
  @Version Long version;
}

Person daenerys = template.insert(new Person("Daenerys"));                            <1>

Person tmp = template.findOne(query(where("id").is(daenerys.getId())), Person.class); <2>

daenerys.setLastname("Targaryen");
template.save(daenerys);                                                              <3>

template.save(tmp); // throws OptimisticLockingFailureException                       <4>
----
<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`.
====

NOTE: Optimistic Locking is only supported with single-entity operations and not for batch operations.

[[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.

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:

.Querying for rows using `CassandraTemplate`
====
[source,java]
----
import static org.springframework.data.cassandra.core.query.Criteria.where;
import static org.springframework.data.cassandra.core.query.Query.query;

…

List<Person> result = cassandraTemplate.select(query(where("age").is(50))
  .and(where("balance").gt(1000.00d)).withAllowFiltering(), Person.class);
----
====

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:

[[cassandra.template.query.criteria]]
==== Methods for the Criteria class

* `CriteriaDefinition` *gt* `(Object value)`: Creates a criterion by using the `>` operator.
* `CriteriaDefinition` *gte* `(Object value)`: Creates a criterion by using the `>=` operator.
* `CriteriaDefinition` *in* `(Object... values)`: Creates a criterion by using the `IN` operator for a varargs argument.
* `CriteriaDefinition` *in* `(Collection<?> collection)`: Creates a criterion by using the `IN` operator using a collection.
* `CriteriaDefinition` *is* `(Object value)`: Creates a criterion by using field matching (`column = value`).
* `CriteriaDefinition` *lt* `(Object value)`: Creates a criterion by using the `<` operator.
* `CriteriaDefinition` *lte* `(Object value)`: Creates a criterion by using the `<=` operator.
* `CriteriaDefinition` *like* `(Object value)`: Creates a criterion by using the `LIKE` operator.
* `CriteriaDefinition` *contains* `(Object value)`: Creates a criterion by using the `CONTAINS` operator.
* `CriteriaDefinition` *containsKey* `(Object key)`: Creates a criterion by using the `CONTAINS KEY` operator.

`Criteria` is immutable once created.

[[cassandra.template.query.query-class]]
==== Methods for the Query class

The `Query` class has some additional methods that you can use to provide options for the query:

* `Query` *by* `(CriteriaDefinition... criteria)`: Used to create a `Query` object.
* `Query` *and* `(CriteriaDefinition criteria)`: Used to add additional criteria to the query.
* `Query` *columns* `(Columns columns)`: Used to define columns to be included in the query results.
* `Query` *limit* `(long limit)`: Used to limit the size of the returned results to the provided limit (used for paging).
* `Query` *pageRequest* `(Pageable pageRequest)`: Used to associate `Sort`, `PagingState`, and `fetchSize` with the query (used for paging).
* `Query` *pagingState* `(ByteBuffer pagingState)`: Used to associate a `ByteBuffer` with the query (used for paging).
* `Query` *queryOptions* `(QueryOptions queryOptions)`: Used to associate `QueryOptions` with the query.
* `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.

[[cassandra.template.query.rows]]
=== Methods for Querying for Rows

The `Query` class has the following methods that return rows:

* `List<T>` *select* `(Query query, Class<T> entityClass)`: Query for a list of objects of type `T` from the table.
* `T` *selectOne* `(Query query, Class<T> entityClass)`: Query for a single object of type `T` from the table.
* `Slice<T>` *slice* `(Query query, Class<T> entityClass)`: Starts or continues paging by querying for a `Slice` of objects of type `T` from the table.
* `Stream<T>` *stream* `(Query query, Class<T> entityClass)`: Query for a stream of objects of type `T` from the table.
* `List<T>` *select* `(String cql, Class<T> entityClass)`: Ad-hoc query for a list of objects of type `T` from the table by providing a CQL statement.
* `T` *selectOne* `(String cql, Class<T> entityClass)`: Ad-hoc query for a single object of type `T` from the table by providing a CQL statement.
* `Stream<T>` *stream* `(String cql, Class<T> entityClass)`: Ad-hoc query for a stream of objects of type `T` from the table by providing a CQL statement.

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.
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:

====
[source,java]
----
List<SWCharacter> all = ops.query(SWCharacter.class)
  .inTable("star_wars")                        <1>
  .all();
----
<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:

====
[source,java]
----
List<Jedi> all = ops.query(SWCharacter.class)    <1>
  .as(Jedi.class)                                <2>
  .matching(query(where("jedi").is(true)))
  .all();
----
<1> The query fields are mapped against the `SWCharacter` type.
<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<?>)`.

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).

[[cassandra.template.prepared-statements]]
== Prepared Statements

CQL statements that are executed multiple times can be prepared and stored in a `PreparedStatement` object to improve query performance.
Both, the driver and Cassandra maintain a mapping of `PreparedStatement` queries to their metadata.
You can use prepared statements through the following abstractions:

* `CqlTemplate` through the choice of API
* `CassandraTemplate` by enabling prepared statements
* Cassandra repositories as they are built on `CassandraTemplate`

[[cassandra.template.prepared-statements.cql]]
=== Using `CqlTemplate`

The `CqlTemplate` class (and its asynchronous and reactive variants) offers various methods accepting static CQL, `Statement` objects and `PreparedStatementCreator`.
Methods accepting static CQL without additional arguments typically run the CQL statement as-is without further processing.
Methods accepting static CQL in combination with an arguments array (such as `execute(String cql, Object... args)` and `queryForRows(String cql, Object... args)`) use prepared statements.
Internally, these methods create a `PreparedStatementCreator` and `PreparedStatementBinder` objects to prepare the statement and later on to bind values to the statement to run it.
Spring Data Cassandra generally uses index-based parameter bindings for prepared statements.

Since Cassandra Driver version 4, prepared statements are cached on the driver level which removes the need to keep track of prepared statements in the application.

The following example shows how to issue a query with a parametrized prepared statement:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=lastName]
----
====

In cases where you require more control over statement preparation and parameter binding (for example, using named binding parameters), you can fully control prepared statement creation and parameter binding by calling query methods with `PreparedStatementCreator` and `PreparedStatementBinder` arguments:

====
[source,java,indent=0]
----
include::../{example-root}/CqlTemplateExamples.java[tags=preparedStatement]
----
====

Spring Data Cassandra ships with classes supporting that pattern in the `cql` package:

* `SimplePreparedStatementCreator` - utility class to create a prepared statement.
* `ArgumentPreparedStatementBinder` - utility class to bind arguments to a prepared statement.

[[cassandra.template.prepared-statements.cassandra-template]]
=== Using `CassandraTemplate`

The `CassandraTemplate` class is built on top of `CqlTemplate` to provide a higher level of abstraction.
The use of prepared statements can be controlled directly on `CassandraTemplate` (and its asynchronous and reactive variants) by calling `setUsePreparedStatements(false)` respective `setUsePreparedStatements(true)`.
Note that the use of prepared statements by `CassandraTemplate` is enabled by default.

The following example shows the use of methods that generate and that accept CQL:

====
[source,java,indent=0]
----
include::../{example-root}/CassandraTemplateExamples.java[tags=preparedStatement]
----
====

Calling entity-bound methods such as `select(Query, Class<T>)` or `update(Query, Update, Class<T>)` build CQL statements themselves to perform the intended operations.
Some `CassandraTemplate` methods (such as `select(Statement<?>, Class<T>)`) also accepts CQL `Statement` objects as part of their API.

It's possible to participate in prepared statements when calling methods accepting a `Statement` with a `SimpleStatement` object.
The template API extracts the query string and parameters (positional and named parameters) and uses these to prepare, bind, and run the statement.
Non-``SimpleStatement`` objects cannot be used with prepared statements.

[[cassandra.template.prepared-statements.caching]]
=== Caching Prepared Statements

Since Cassandra driver 4.0, prepared statements are cached by the `CqlSession` cache so it is okay to prepare the same string twice.
Previous versions required caching of prepared statements outside of the driver.
See also the https://docs.datastax.com/en/developer/java-driver/latest/manual/core/statements/prepared/[Driver documentation on Prepared Statements] for further reference.
