327 lines
13 KiB
XML
327 lines
13 KiB
XML
<?xml version='1.0'?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<chapter id="cassandra.core">
|
|
<title>Cassandra support</title>
|
|
<para>The Cassandra support contains a wide range of features which are
|
|
summarized below.</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Spring configuration support using Java based @Configuration classes
|
|
or an XML namespace for a Cassandra driver instance and replica sets</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>CassandraTemplate helper class that increases productivity performing
|
|
common Cassandra operations. Includes integrated object mapping between CQL
|
|
Tables and POJOs.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Exception translation into Spring's portable Data Access
|
|
Exception hierarchy</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Feature Rich Object Mapping integrated with Spring's Conversion
|
|
Service</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Annotation based mapping metadata but extensible to support other
|
|
metadata formats</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Persistence and mapping lifecycle events</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Java based Query, Criteria, and Update DSLs</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Automatic implementation of Repository interfaces including support
|
|
for custom finder methods.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>For most tasks you will find yourself using <classname>
|
|
CassandraTemplate</classname> or the Repository support that both leverage the
|
|
rich mapping functionality. CassandraTemplate is the place to look for
|
|
accessing functionality such as incrementing counters or ad-hoc CRUD
|
|
operations. CassandraTemplate also provides callback methods so that it is
|
|
easy for you to get a hold of the low level API artifacts such as <literal>
|
|
com.datastax.driver.core.Session</literal> to communicate directly with
|
|
Cassandra. The goal with naming conventions on various API artifacts is to
|
|
copy those in the base DataStax Java driver so you can easily map your
|
|
existing knowledge onto the Spring APIs.</para>
|
|
<section id="cassandra-getting-started">
|
|
<title>Getting Started</title>
|
|
<para>Spring Data Cassandra uses the DataStax Java Driver version 2.X, which
|
|
supports DataStax Enterprise 4/Cassandra 2.0, and Java SE 6 or higher. The
|
|
latest commercial release (2.X as of this writing) is recommended. An easy
|
|
way to bootstrap setting up a working environment is to create a Spring based
|
|
project in <ulink url="http://spring.io/tools/sts">STS</ulink>.</para>
|
|
<para>First you need to set up a running Cassandra server.</para>
|
|
<para>To create a Spring project in STS go to File -> New -> Spring
|
|
Template Project -> Simple Spring Utility Project -> press Yes when
|
|
prompted. Then enter a project and a package name such as
|
|
org.spring.cassandra.example.</para>
|
|
<para>Then add the following to pom.xml dependencies section.</para>
|
|
<programlisting lang="" language="xml"><dependencies>
|
|
|
|
<!-- other dependency elements omitted -->
|
|
|
|
<dependency>
|
|
<groupId>org.springframework.data</groupId>
|
|
<artifactId>spring-data-cassandra</artifactId>
|
|
<version>1.0.0.RELEASE</version>
|
|
</dependency>
|
|
|
|
</dependencies></programlisting>
|
|
<para>Also change the version of Spring in the pom.xml to be</para>
|
|
<programlisting lang="" language="xml"><spring.framework.version>3.2.8.RELEASE</spring.framework.version></programlisting>
|
|
<para>You will also need to add the location of the Spring Milestone
|
|
repository for maven to your pom.xml which is at the same level of your
|
|
<dependencies/> element</para>
|
|
<programlisting language="xml"><repositories>
|
|
<repository>
|
|
<id>spring-milestone</id>
|
|
<name>Spring Maven MILESTONE Repository</name>
|
|
<url>http://repo.spring.io/libs-milestone</url>
|
|
</repository>
|
|
</repositories></programlisting>
|
|
<para>The repository is also
|
|
<ulink url="http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/data/">
|
|
browseable here</ulink>.</para>
|
|
<para>Create a simple Employee class to persist.</para>
|
|
<para>
|
|
<programlisting>package org.spring.cassandra.example;
|
|
|
|
import org.springframework.data.cassandra.mapping.PrimaryKey;
|
|
import org.springframework.data.cassandra.mapping.Table;
|
|
|
|
@Table
|
|
public class Person {
|
|
|
|
@PrimaryKey
|
|
private String id;
|
|
|
|
private String name;
|
|
private int age;
|
|
|
|
public Person(String id, String name, int age) {
|
|
this.id = id;
|
|
this.name = name;
|
|
this.age = age;
|
|
}
|
|
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
public int getAge() {
|
|
return age;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
|
|
}
|
|
|
|
}</programlisting>
|
|
</para>
|
|
<para>And a main application to run</para>
|
|
<para>
|
|
<programlisting>package org.spring.cassandra.example;
|
|
|
|
import java.net.InetAddress;
|
|
import java.net.UnknownHostException;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.data.cassandra.core.CassandraOperations;
|
|
import org.springframework.data.cassandra.core.CassandraTemplate;
|
|
|
|
import com.datastax.driver.core.Cluster;
|
|
import com.datastax.driver.core.Session;
|
|
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
|
import com.datastax.driver.core.querybuilder.Select;
|
|
|
|
public class CassandraApp {
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(CassandraApp.class);
|
|
|
|
private static Cluster cluster;
|
|
private static Session session;
|
|
|
|
public static void main(String[] args) {
|
|
|
|
try {
|
|
|
|
cluster = Cluster.builder().addContactPoints(InetAddress.getLocalHost()).build();
|
|
|
|
session = cluster.connect("mykeyspace");
|
|
|
|
CassandraOperations cassandraOps = new CassandraTemplate(session);
|
|
|
|
cassandraOps.insert(new Person("1234567890", "David", 40));
|
|
|
|
Select s = QueryBuilder.select().from("person");
|
|
s.where(QueryBuilder.eq("id", "1234567890"));
|
|
|
|
LOG.info(cassandraOps.queryForObject(s, Person.class).getId());
|
|
|
|
cassandraOps.truncate("person");
|
|
|
|
} catch (UnknownHostException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
}
|
|
}
|
|
</programlisting>
|
|
</para>
|
|
<para>Even in this simple example, there are a few things to observe.</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>You can create an instance of CassandraTemplate with a Cassandra
|
|
Session, derived from the Cluster.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>You must annotate your POJO as a Cassandra @Table, and also annotate
|
|
the @PrimaryKey. Optionally you can override these mapping names to match
|
|
your Cassandra database table and column names.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>You can use CQL String, or the DataStax QueryBuilder to construct you
|
|
queries.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Examples Repository</title>
|
|
<para>After the initial release of Spring Data Cassandra 1.0.0, we will start
|
|
working on a showcase repository with full examples.</para>
|
|
</section>
|
|
<section id="cassandra-connectors">
|
|
<title>Connecting to Cassandra with Spring</title>
|
|
<section id="cassandra-connectors.ext_properties">
|
|
<title>Externalize Connection Properties</title>
|
|
<para>TODO</para>
|
|
</section>
|
|
<section id="cassandra-connectors.xmlconfig">
|
|
<title>XML Configuration</title>
|
|
<para>TODO</para>
|
|
</section>
|
|
<section id="cassandra-connectors.javaconfig">
|
|
<title>Java Configuration</title>
|
|
<para>TODO</para>
|
|
</section>
|
|
</section>
|
|
<section id="cassandra.auditing">
|
|
<title>General auditing configuration</title>
|
|
<para>Auditing support is not available in the current version.</para>
|
|
</section>
|
|
<section id="cassandra-template">
|
|
<title>Introduction to CassandraTemplate</title>
|
|
<section id="cassandra-template.instantiating" label=" ">
|
|
<title>Instantiating CassandraTemplate</title>
|
|
</section>
|
|
</section>
|
|
<section id="cassandra-template.save-update-remove">
|
|
<title>Saving, Updating, and Removing Rows</title>
|
|
<para><classname>CassandraTemplate</classname> provides a simple way for you
|
|
to save, update, and delete your domain objects and map those objects to
|
|
documents stored in Cassandra.</para>
|
|
<section id="cassandra-template.id-handling">
|
|
<title>How the Composite Primary Key fields are handled in the mapping
|
|
layer</title>
|
|
<para>Cassandra requires that you have at least 1 Partition Key field for a
|
|
CQL Table. Alternately, you can have one or more Clustering Key
|
|
fields.</para>
|
|
<para>TODO With Examples</para>
|
|
</section>
|
|
<section id="cassandra-template.type-mapping">
|
|
<title>Type mapping</title>
|
|
</section>
|
|
<section id="cassandra-template.save-insert">
|
|
<title>Methods for saving and inserting rows</title>
|
|
</section>
|
|
<section id="cassandra-template-update">
|
|
<title>Updating rows in a CQL table</title>
|
|
</section>
|
|
<section id="cassandra-template.upserts">
|
|
<title>Upserting rows in a CQL table</title>
|
|
</section>
|
|
<section id="cassandra-template.find-and-upsert">
|
|
<title>Finding and Upserting rowa in a CQL table</title>
|
|
</section>
|
|
<section id="cassandra-template.delete">
|
|
<title>Methods for removing rows</title>
|
|
</section>
|
|
</section>
|
|
<section id="cassandra.query">
|
|
<title>Querying CQL Tables</title>
|
|
</section>
|
|
<section id="cassandra.custom-converters">
|
|
<title>Overriding default mapping with custom converters</title>
|
|
<para>In order to have more fine grained control over the mapping process you
|
|
can register Spring converters with the <classname>
|
|
CassandraConverter</classname> implementations such as the <classname>
|
|
MappingCassandraConverter</classname>.</para>
|
|
<para>The <classname>MappingCassandraConverter</classname> checks to see if
|
|
there are any Spring converters that can handle a specific class before
|
|
attempting to map the object itself. To 'hijack' the normal mapping
|
|
strategies of the <classname>MappingCassandraConverter</classname>, perhaps
|
|
for increased performance or other custom mapping needs, you first need to
|
|
create an implementation of the Spring <interfacename>
|
|
Converter</interfacename> interface and then register it with the
|
|
MappingConverter.</para>
|
|
<note>
|
|
<para>For more information on the Spring type conversion service see the
|
|
reference docs
|
|
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert">
|
|
here</ulink>.</para>
|
|
</note>
|
|
<section id="cassandra.custom-converters.writer">
|
|
<title>Saving using a registered Spring Converter</title>
|
|
</section>
|
|
<section id="cassandra.custom-converters.reader">
|
|
<title>Reading using a Spring Converter</title>
|
|
</section>
|
|
<section id="cassandra.custom-converters.xml">
|
|
<title>Registering Spring Converters with the CassandraConverter</title>
|
|
</section>
|
|
<section id="cassandra.converter-disambiguation">
|
|
<title>Converter disambiguation</title>
|
|
</section>
|
|
</section>
|
|
<section id="cassandra-template.commands">
|
|
<title>Executing Commands</title>
|
|
<section id="cassandra-template.commands.execution">
|
|
<title>Methods for executing commands</title>
|
|
</section>
|
|
</section>
|
|
<section id="cassandra.mapping-usage.events">
|
|
<title>Lifecycle Events</title>
|
|
</section>
|
|
<section id="cassandra.exception">
|
|
<title>Exception Translation</title>
|
|
<para>The Spring framework provides exception translation for a wide variety
|
|
of database and mapping technologies. This has traditionally been for JDBC
|
|
and JPA. The Spring support for Cassandra extends this feature to the
|
|
Cassandra Database by providing an implementation of the <classname>
|
|
org.springframework.dao.support.PersistenceExceptionTranslator</classname>
|
|
interface.</para>
|
|
<para>The motivation behind mapping to Spring's
|
|
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/dao.html#dao-exceptions">
|
|
consistent data access exception hierarchy</ulink> is that you are then able
|
|
to write portable and descriptive exception handling code without resorting
|
|
to coding against Cassandra Exceptions. All of Spring's data access
|
|
exceptions are inherited from the root <classname>
|
|
DataAccessException</classname> class so you can be sure that you will be
|
|
able to catch all database related exception within a single try-catch
|
|
block.</para>
|
|
</section>
|
|
<section id="cassandra.executioncallback">
|
|
<title>Execution callbacks</title>
|
|
</section>
|
|
</chapter>
|