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
Contents
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:
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); |
2. Create SpringBoot project
– Using SpringToolSuite, create a SpringBoot project. Then add data-cassandra dependency:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-cassandra</artifactId> </dependency> |
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<Customer, String> { @Query(value="SELECT * FROM customer WHERE firstname=?0") public List<Customer> findByFirstname(String firstname); @Query("SELECT * FROM customer WHERE age > ?0") public List<Customer> findCustomerHasAgeGreaterThan(int age); } |
*Update for Spring Boot 2 (Spring Data Cassandra 2) with new @AllowFiltering
annotation:
public interface CustomerRepository extends CassandraRepository<Customer, String> { @AllowFiltering public List<Customer> findByFirstname(String firstname); @AllowFiltering public List<Customer> 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<Customer> peters = customerRepository.findByFirstname("Peter"); peters.forEach(System.out::println); System.out.println("===================Lookup Customers from Cassandra by Age==================="); List<Customer> 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<Customer, String> { @Query(value="SELECT * FROM customer WHERE firstname=?0") public List<Customer> findByFirstname(String firstname); @Query("SELECT * FROM customer WHERE age > ?0 ALLOW FILTERING") public List<Customer> 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:
III. Sourcecode
Last updated on March 19, 2018.
Can we not use a @Query with update command in it like below
????
Hi saikiran,
You can update data by finding the row by id, change data, then save new item:
For more details, please visit:
Angular 4 + Spring Boot + Cassandra CRUD example
Regards,
JSA.
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
Hello Vishrut Sharma,
We had checked sourcecode and it works well!
For double check and practice with the tutorial, please follow 2 step:
1. Set up Apache Cassandra
2. Download sourcecode then run and check results
Regards,
JSA
how to configure more than one key-space and for different environments.
which class need to override for this.
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
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
i need help…”error”: “Internal Server Error”,
“message”: “Couldn’t find PersistentEntity for type class java.lang.Integer!”,
how to solve this error…