How to start Spring Data Cassandra with SpringBoot

Apache Cassandra database is a NoSql solution for scalability & high availability. In the tutorial, JavaSampleApproach will show you how to start Spring Data Cassandra by sample code.

Related article:
How to start SpringBoot ElasticSearch using Spring Data
Couchbase – How to create a Spring Jpa Couchbase application with SpringBoot
SpringData Reactive Cassandra Repositories | SpringBoot
Angular 4 + Spring Boot + Cassandra CRUD example
Angular + Spring WebFlux + Spring Data Reactive Cassandra example | Full-Reactive Angular Http Client – Spring Boot RestApi Server


I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: 1.5.1.RELEASE
– DataStax Community Edition for Apache Cassandra: v3.9.0

II. Practice

Step to do:
– Set up Apache Cassandra
– Create SpringBoot project
– Create a mapping model
– Create a Cassandra repository
– Create a test client
– Run & check result

1. Set up Apache Cassandra

Download Apache Cassandra:
– For Linux, go to the site Downloading Cassandra.
– For Windows, go to the site DataStax Distribution.

In the tutorial, environment: {Windows 10, Apache Cassandra – v3.9.0} to demo. After downloading, we have a file: datastax-ddc-64bit-3.9.0.msi. Now just double click on datastax-ddc-64bit-3.9.0.msi then do step by step to install.

Now start Cassandra server:

cassandra start sever

Open Cassandra CQL Shell to create Cassandra table:

– Create Cassandra keyspace with name javasampleapproach:

create keyspace javasampleapproach with replication={'class':'SimpleStrategy', 'replication_factor':1};

– Create customer table for javasampleapproach keyspace:

use javasampleapproach;

CREATE TABLE customer(
   id int PRIMARY KEY,
   firstname text,
   lastname text,
   age int
);

– Create an index on firstname column:

CREATE INDEX ON javasampleapproach.customer (firstname);

springboot-cassandra create table

2. Create SpringBoot project

– Using SpringToolSuite, create a SpringBoot project. Then add data-cassandra dependency:


	org.springframework.boot
	spring-boot-starter-data-cassandra

3. Create a mapping model

– Create Customer.java:

package com.javasampleapproach.cassandra.model;

import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;

@Table
public class Customer {
	
	@PrimaryKey
	private int id;
	private String firstname;
	private String lastname;
	private int age;
	
	public Customer(){}
	
	public Customer(int id, String firstname, String lastname, int age){
		this.id = id;
		this.firstname = firstname;
		this.lastname = lastname;
		this.age = age;
	}
	
	public void setId(int id){
		this.id = id;
	}
	
	public int getId(){
		return this.id;
	}
	
	public void setFirstname(String firstname){
		this.firstname = firstname;
	}
	
	public String getFirstname(){
		return this.firstname;
	}
	
	public void setLastname(String lastname){
		this.lastname = lastname;
	}
	
	public String getLastname(){
		return this.lastname;
	}
	
	public void setAge(int age){
		this.age = age;
	}
	
	public int getAge(){
		return this.age;
	}
	
	@Override
	public String toString() {
		return String.format("Customer[id=%d, firstName='%s', lastName='%s', age=%d]", this.id,
				this.firstname, this.lastname, this.age);
	}
}

@Table: identifies a domain object to be persisted to Cassandra as a table.
@PrimaryKey: identifies the primary key field of the entity.

4. Create a Cassandra repository

– Open application.properties, configure spring.data.cassandra:

spring.data.cassandra.keyspace-name=javasampleapproach
spring.data.cassandra.contact-points=grokonez.com
spring.data.cassandra.port=9042

– Spring Data supports basic operations for Cassandra. But more limited than JPA repositories, so we need use @Query.

package com.javasampleapproach.cassandra.repository;

import java.util.List;

import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.repository.CrudRepository;

import com.javasampleapproach.cassandra.model.Customer;

public interface CustomerRepository extends CrudRepository {
	
	@Query(value="SELECT * FROM customer WHERE firstname=?0")
	public List findByFirstname(String firstname);

	@Query("SELECT * FROM customer WHERE age > ?0")
	public List findCustomerHasAgeGreaterThan(int age);
}	

*Update for Spring Boot 2 (Spring Data Cassandra 2) with new @AllowFiltering annotation:

public interface CustomerRepository extends CassandraRepository {

	@AllowFiltering
	public List findByFirstname(String firstname);

	@AllowFiltering
	public List findByAgeGreaterThan(int age);
}
5. Create a test client

– Use repository: CustomerRepository

...  
@Autowired
CustomerRepository customerRepository;
...

Implement 3 functions:
clearData() is used to empty customer table.
saveData() is used to persist Customer entities to Cassandra.
lookup() is used to load all records and show all on console.

package com.javasampleapproach.cassandra;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.javasampleapproach.cassandra.model.Customer;
import com.javasampleapproach.cassandra.repository.CustomerRepository;

@SpringBootApplication
public class SpringDataCassandraApplication implements CommandLineRunner{
	
    @Autowired
    CustomerRepository customerRepository;

	public static void main(String[] args) {
		SpringApplication.run(SpringDataCassandraApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		clearData();
		saveData();
		lookup();
	}
	
	public void clearData(){
		customerRepository.deleteAll();
	}
	
	public void saveData(){
		System.out.println("===================Save Customers to Cassandra===================");
		Customer cust_1 = new Customer(1, "Peter", "Smith", 20);
        Customer cust_2 = new Customer(2, "Mary", "Taylor", 25);
        Customer cust_3 = new Customer(3, "Peter", "Brown", 30);
        Customer cust_4 = new Customer(4, "Lauren", "Taylor", 20);
        Customer cust_5 = new Customer(5, "Lauren", "Flores", 45);
        Customer cust_6 = new Customer(6, "Peter", "Williams", 20);
 
        // save customers to ElasticSearch
        customerRepository.save(cust_1);
        customerRepository.save(cust_2);
        customerRepository.save(cust_3);
        customerRepository.save(cust_4);
        customerRepository.save(cust_5);
        customerRepository.save(cust_6);
	}
	
	public void lookup(){
		System.out.println("===================Lookup Customers from Cassandra by Firstname===================");
		List peters = customerRepository.findByFirstname("Peter");
		peters.forEach(System.out::println);

		System.out.println("===================Lookup Customers from Cassandra by Age===================");
		List custsAgeGreaterThan25 = customerRepository.findCustomerHasAgeGreaterThan(25);
		custsAgeGreaterThan25.forEach(System.out::println);
	}
}

6. Run & check result

– Build & Run the project with SpringBoot App mode.
-> Meet an InvalidQueryException exception when executing lookup function – findCustomerHasAgeGreaterThan(int age):

Caused by: com.datastax.driver.core.exceptions.InvalidQueryException: Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING
	at com.datastax.driver.core.Responses$Error.asException(Responses.java:136) ~[cassandra-driver-core-3.1.4.jar:na]
	at com.datastax.driver.core.DefaultResultSetFuture.onSet(DefaultResultSetFuture.java:179) ~[cassandra-driver-core-3.1.4.jar:na]

-> Solution:
Use ALLOW FILTERING in Query:

public interface CustomerRepository extends CrudRepository {
	
	@Query(value="SELECT * FROM customer WHERE firstname=?0")
	public List findByFirstname(String firstname);

	@Query("SELECT * FROM customer WHERE age > ?0 ALLOW FILTERING")
	public List findCustomerHasAgeGreaterThan(int age);
}	

– Build & Run the project with SpringBoot App mode again.
Logs:

...
===================Save Customers to Cassandra===================
===================Lookup Customers from Cassandra by Firstname===================
Customer[id=1, firstName='Peter', lastName='Smith', age=20]
Customer[id=6, firstName='Peter', lastName='Williams', age=20]
Customer[id=3, firstName='Peter', lastName='Brown', age=30]
===================Lookup Customers from Cassandra by Age===================
Customer[id=5, firstName='Lauren', lastName='Flores', age=45]
Customer[id=3, firstName='Peter', lastName='Brown', age=30]
...

Cassandra CQL Shell:

springboot-cassandra - select after saving

III. Sourcecode

SpringDataCassandra



By grokonez | May 1, 2017.

Last updated on March 19, 2018.



Related Posts


8 thoughts on “How to start Spring Data Cassandra with SpringBoot”

  1. Can we not use a @Query with update command in it like below

    @Query(value = "UPDATE AreacodeVO SET area ='hy' WHERE id = 1;")
    

    ????

    1. Hi saikiran,

      You can update data by finding the row by id, change data, then save new item:

      @RestController
      public class CustomerController {
      	@PutMapping("/customers/{id}")
      	public ResponseEntity updateCustomer(@PathVariable("id") UUID id, @RequestBody Customer customer) {
      		System.out.println("Update Customer with ID = " + id + "...");
      
      		Customer customerData = customerRepository.findOne(BasicMapId.id("id", id));
      		if (customerData == null) {
      			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
      		}
      		customerData.setName(customer.getName());
      		customerData.setAge(customer.getAge());
      		customerData.setActive(customer.isActive());
      		Customer updatedcustomer = customerRepository.save(customerData);
      		return new ResponseEntity<>(updatedcustomer, HttpStatus.OK);
      	}
      }
      

      For more details, please visit:
      Angular 4 + Spring Boot + Cassandra CRUD example

      Regards,
      JSA.

  2. hi,

    i tried the tutorial step by step.
    I feel like , i am alnmost there, but i get one error like this
    ——————————————-
    ***************************
    APPLICATION FAILED TO START
    ***************************

    Description:

    Field patient_info_Repo in com.datastax.cassandra.cassandradrivercore.SpringCassandraApplication required a bean of type ‘com.datastax.cassandra.cassandradrivercore.patient_info_repository’ that could not be found.

    Action:

    Consider defining a bean of type ‘com.datastax.cassandra.cassandradrivercore.patient_info_repository’ in your configuration.

    ————————————
    My guess is the @Autowired is unable to find its corresponding bean.

    Please help me get rid of this problem.

    Thanks in advance

  3. there is an error in your code
    see:-
    COMPILATION ERROR :
    ————————————————————-
    com/javasampleapproach/cassandra/model/Customer.java:[3,50] package org.springframework.data.cassandra.mapping does not exist
    com/javasampleapproach/cassandra/model/Customer.java:[4,50] package org.springframework.data.cassandra.mapping does not exist
    com/javasampleapproach/cassandra/model/Customer.java:[6,2] cannot find symbol
    symbol: class Table
    com/javasampleapproach/cassandra/model/Customer.java:[9,10] cannot find symbol
    symbol: class PrimaryKey
    location: class com.javasampleapproach.cassandra.model.Customer
    4 errors
    ————————————————————-
    ————————————————————————
    BUILD FAILURE

  4. Hi , new to Cassandra , when I executed this source code aganist a three node cassandra cluster it is throwing below error , how to fix this , please help me , my keyspace replication factor is 2.

    Caused by: org.springframework.cassandra.support.exception.CassandraTruncateException: Error during truncate: Cannot achieve consistency level ALL; nested exception is com.datastax.driver.core.exceptions.TruncateException: Error during truncate: Cannot achieve consistency level ALL
    at org.springframework.cassandra.support.CassandraExceptionTranslator.translateExceptionIfPossible(CassandraExceptionTranslator.java:100) ~[spring-cql-1.5.3.RELEASE.jar:na]

    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504) ~[spring-data-commons-1.13.3.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489) ~[spring-data-commons-1.13.3.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at com.sun.proxy.$Proxy51.deleteAll(Unknown Source) ~[na:na]
    at com.javasampleapproach.cassandra.SpringDataCassandraApplication.clearData(SpringDataCassandraApplication.java:31) [classes/:na]
    at com.javasampleapproach.cassandra.SpringDataCassandraApplication.run(SpringDataCassandraApplication.java:25) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
    … 6 common frames omitted

  5. i need help…”error”: “Internal Server Error”,
    “message”: “Couldn’t find PersistentEntity for type class java.lang.Integer!”,

    how to solve this error…

Got Something To Say:

Your email address will not be published. Required fields are marked *

*