DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Databases
  4. Spring Data Support for Cassandra 3

Spring Data Support for Cassandra 3

Using Spring Data with Cassandra 3 extends Spring's power into more NoSQL. This detailed tutorial includes setting up Apache Cassandra and some basic interactions.

Biju Kunjummen user avatar by
Biju Kunjummen
·
Feb. 01, 17 · Tutorial
Like (4)
Save
Tweet
Share
12.32K Views

Join the DZone community and get the full member experience.

Join For Free

One of the items that caught my eye from the announcement of the new Spring Data release train named Ingalls was that Spring Data Cassandra finally supports Cassandra 3+. So I revisited one of my old samples and tried it with a newer version of Cassandra.

Installing Cassandra

The first step is to install a local version of Cassandra, and I continue to find the ccm tool to be outstanding in being able to bring up and tear down a small cluster. Here is the command that I am running to bring up a three-node Apache Cassandra 3.9-based cluster.

ccm create test -v 3.9 -n 3 -s --vnodes


Create Schemas

Connect to a node in the cluster:

ccm node1 cqlsh
 
CREATE KEYSPACE IF NOT EXISTS sample WITH replication = {'class':'SimpleStrategy', 'replication_factor':1};


Next, I need to create the tables to hold the data. A general Cassandra recommendation is to model the tables based on query patterns — given this lets me first define a table to hold the basic "hotel" information:

CREATE TABLE IF NOT EXISTS  sample.hotels (
    id UUID,
    name varchar,
    address varchar,
    state varchar,
    zip varchar,
    primary key((id), name)
);


Assuming I have to support two query patterns — a retrieval of hotels based on, say, the first letter and a retrieval of hotels by state — I have a "hotels_by_letter" denormalized table to support retrieval by "first letter":

CREATE TABLE IF NOT EXISTS  sample.hotels_by_letter (
    first_letter varchar,
    hotel_name varchar,
    hotel_id UUID,
    address varchar,
    state varchar,
    zip varchar,
    primary key((first_letter), hotel_name, hotel_id)
);


And just for variety, let's try a "hotels_by_state" materialized view to support retrieval by the state that the hotels are in:

CREATE MATERIALIZED VIEW sample.hotels_by_state AS
    SELECT id, name, address, state, zip FROM hotels
        WHERE state IS NOT NULL AND id IS NOT NULL AND name IS NOT NULL
    PRIMARY KEY ((state), name, id)
    WITH CLUSTERING ORDER BY (name DESC)


Coding Repositories

On the Java side, since I am persisting and querying a simple domain type called "Hotel", it looks like this:

@Table("hotels")
public class Hotel implements Serializable {
    @PrimaryKey
    private UUID id;
    private String name;
    private String address;
    private String state;
    private String zip;
    ...
}


Now, to be able to perform a basic CRUD operation on this entity, all that is required is a repository interface as shown in the following code:

import cass.domain.Hotel;
import org.springframework.data.repository.CrudRepository;
 
import java.util.UUID;
 
public interface HotelRepository extends CrudRepository<Hotel, UUID>, HotelRepositoryCustom {}


This repository is additionally inheriting from a HotelRepositoryCustom interface, which provides the custom finders to support retrieval by first name and state.

Now to persist a Hotel entity, all I have to do is to call the repository method:

hotelRepository.save(hotel);


The data in the materialized view is automatically synchronized and maintained by Cassandra, but the data in the "hotels_by_letter" table has to be managed through code, so I have another repository defined to maintain data in this table:

public interface HotelByLetterRepository 
        extends CrudRepository<HotelByLetter, HotelByLetterKey>, HotelByLetterRepositoryCustom {}


The custom interface and its implementation are to facilitate searching this table on queries based on the first letter of the hotel name and are implemented this way through a custom repository implementation feature of Spring data Cassandra.

import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.stereotype.Repository;
 
import java.util.List;
 
@Repository
public class HotelRepositoryImpl implements HotelRepositoryCustom {
 
    private final CassandraTemplate cassandraTemplate;
 
    @Autowired
    public HotelRepositoryImpl(CassandraTemplate cassandraTemplate) {
        this.cassandraTemplate = cassandraTemplate;
    }
 
    @Override
    public List<Hotel> findByState(String state) {
        Select select = QueryBuilder.select().from("hotels_by_state");
        select.where(QueryBuilder.eq("state", state));
        return this.cassandraTemplate.select(select, Hotel.class);
    }
}
 
@Repository
public class HotelByLetterRepositoryImpl implements HotelByLetterRepositoryCustom {
    private final CassandraTemplate cassandraTemplate;
 
    public HotelByLetterRepositoryImpl(CassandraTemplate cassandraTemplate) {
        this.cassandraTemplate = cassandraTemplate;
    }
 
    @Override
    public List<HotelByLetter> findByFirstLetter(String letter) {
        Select select = QueryBuilder.select().from("hotels_by_letter");
        select.where(QueryBuilder.eq("first_letter", letter));
        return this.cassandraTemplate.select(select, HotelByLetter.class);
    }
}


Given these repository classes — custom repositories that provide query support — the rest of the code is to wire everything together, which Spring Boot's Cassandra Auto Configuration facilitates.

That is essentially all there is to it. Spring Data Cassandra makes it ridiculously simple to interact with Cassandra 3+. 

A complete working project is, I believe, a far better way to get familiar with this excellent library, and I have such a sample available in my GitHub repo here.

Spring Data Data (computing) Spring Framework Database

Published at DZone with permission of Biju Kunjummen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Deploying Java Serverless Functions as AWS Lambda
  • How to Create a Real-Time Scalable Streaming App Using Apache NiFi, Apache Pulsar, and Apache Flink SQL
  • Better Performance and Security by Monitoring Logs, Metrics, and More
  • Differences Between Site Reliability Engineer vs. Software Engineer vs. Cloud Engineer vs. DevOps Engineer

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: