spring

Spring Data Cassandra Example

In the previous example, we demonstrated the configuration of Spring Data with GemFire, an in-memory NoSQL Database. So continuing on the same series, in this example we shall demonstrate how to connect Spring Data Application to Apache Cassandra, a Column based NoSql Database.

Cassandra is a Distributed Database Management System that can handle large amounts of data with data replication across multiple data-centres so that there is no single point of failure. It uses CQL as its query language which has syntax quite similar to its homonym SQL.

As Cassandra is a new technology, it has its own set of challenges and learning curve. To help with this, Spring Data hides the complexity of writing queries and other configuration stuff. Spring Data Cassandra offers the users a familiar interface to those who have used Spring Data in the past.

1. Implementation

We need to install Cassandra Database Server, first. For Windows System, Cassandra can be downloaded from plannetcassandra and for Linux System it can be downloaded from the Apache Mirrors.

Once Cassandra is up and running, we need to create a key-space which corresponds to the schema in the RDBMS world. We then create a column family in cassandra which can be colloquially referred to a RDMBS Table.
Then, we need to have following JAR Files to connect to Cassandra Server:

  • aopalliancejar
  • cassandra-driver-core.jar
  • commons-logging.jar
  • guava.jar
  • metrics-core.jar
  • slf4j-api.jar
  • spring-aop-RELEASE.jar
  • spring-beans-RELEASE.jar
  • spring-context-RELEASE.jar
  • spring-core-RELEASE.jar
  • spring-cql-RELEASE.jar
  • spring-data-cassandra-RELEASE.jar
  • spring-data-commons-RELEASE.jar
  • spring-expression-RELEASE.jar
  • spring-tx-RELEASE.jar

Create a project in eclipse or any IDE and add the JAR files downloaded above. Now that the project is setup, we start with the coding phase :

We create a PoJo which maps the Column family and is the basic unit that is to be persisted in the Cassandra Database.

Person.java

package com.jcg.examples.entity;

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

@Table("Person")	
public class Person
{
		@PrimaryKey
		private Integer pId;	
		
		private String name;

		public Integer getpId()
    {
    		return pId;
    }

		public void setpId(Integer pId)
    {
    		this.pId = pId;
    }

		public String getName()
    {
    		return name;
    }
		
		public void setName(String name)
    {
    		this.name = name;
    }

		@Override
    public String toString()
    {
		    return "Person [pId=" + pId + ", name=" + name + "]";
    }

		@Override
    public int hashCode()
    {
		    final int prime = 31;
		    int result = 1;
		    result = prime * result + ((name == null) ? 0 : name.hashCode());
		    result = prime * result + ((pId == null) ? 0 : pId.hashCode());
		    return result;
    }

		@Override
    public boolean equals(Object obj)
    {
		    if (this == obj)
				    return true;
		    if (obj == null)
				    return false;
		    if (getClass() != obj.getClass())
				    return false;
		    Person other = (Person) obj;
		    if (name == null)
		    {
				    if (other.name != null)
						    return false;
		    }
		    else if (!name.equals(other.name))
				    return false;
		    if (pId == null)
		    {
				    if (other.pId != null)
						    return false;
		    }
		    else if (!pId.equals(other.pId))
				    return false;
		    return true;
    }

}

We annotate the class with @Table annotation to mark it as PoJo which is being mapped and the column-family name to which it should correspond in the Key-Space. @PrimaryKey simply marks the property as the Primary key.

Now that the PoJo is ready we need to create the DAO layer. The PersonRepo interface does the job of this.

PersonRepo.java

package com.jcg.examples.repo;

import org.springframework.data.repository.CrudRepository;

import com.jcg.examples.entity.Person;

public interface PersonRepo extends CrudRepository<Person, String>
{

                @Query("Select * from person where pid=?0")
		public Person fetchByPId(int pid);

}

The Spring Data provides a number of inbuilt method for manipulating the Data. We need not write the queries for basic data manipulation and reading. It is achieved by extending the CrudRepository and declaring the proper Generics as per the PoJo, which in our case is the Person, String. In case the Developer is not satisfied with the existing method, he can create his own method by specifying the Query using the @Query annotation.

The Spring IoC Container creates an instance of this Repository and makes it available to be used as a Bean.

The last and the most important part is to configure the Spring Container using the spring-config.xml :

Spring-config.xml

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/cql http://www.springframework.org/schema/cql/spring-cql-1.0.xsd
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/cassandra http://www.springframework.org/schema/data/cassandra/spring-cassandra.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


	<cassandra:cluster id="cassandraCluster"
		contact-points="127.0.0.1" port="9042" />

        <cassandra:converter />

	<cassandra:session id="cassandraSession" cluster-ref="cassandraCluster"
		keyspace-name="jcg" />

	<cassandra:template id="cqlTemplate" />
	

	<cassandra:repositories base-package="com.jcg.examples.repo" />

	<cassandra:mapping entity-base-packages="com.jcg.examples.entity" />
	

</beans:beans>

  • Line 11 :
  • Configuring the Cassandra cluster. The default port in 9042.

  • Line 14 :
  • Cassandra Session can be colloquially referred to as a Sort of connection pool to connect to the cluster. We configure the cassandra session for the key-space "jcg".

  • Line 17 :
  • Cassandra Template can be used to execute queries. But in this example we are creating only because it is dependency to create the Cassandra Repositories for the PoJos.

  • Line 20 :
  • Scan the packages for initializing Cassandra Repositories.

  • Line 22 :
  • Declare Mapping for the PoJos.

Now that all is set, let’s run the application and test out the code! Here’s Application class that loads the XML file to instantiate the Spring Container and execute a few queries.

Application.java

package com.jcg.examples.test;


import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

import com.jcg.examples.entity.Person;
import com.jcg.examples.repo.PersonRepo;


public class Application
{
		public static void main(String[] args)
		{
			ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new ClassPathResource("resources/spring-config.xml").getPath());
			PersonRepo personRepo = context.getBean(PersonRepo.class);
			Person personAchilles = new Person();
			personAchilles.setpId(1);
			personAchilles.setName("Achilles");
			personRepo.save(personAchilles);
			Person personHektor = new Person();
			personHektor.setpId(2);
			personHektor.setName("Hektor");
			personRepo.save(personHektor);
			
			Iterable<Person> personList = personRepo.findAll();
			System.out.println("Person List : ");
			for (Person person : personList)
            {
		        System.out.println(person);
            }
			
            System.out.println("Person with Id 1 is "+personRepo.fetchByPId(1));
	
        	context.close();

		}
}


In the Application class we created two instances of Person class and persisted them to the Cassandra Database. We then fetch all the records in the Person Column family and print them on the screen. Then we executed a query via the personRepo object to fetch the instance by specifying the Primary Key.

Here’s the sample output of the program :

Aug 02, 2015 2:56:27 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@78221c75: startup date [Sun Aug 02 02:56:27 IST 2015]; root of context hierarchy
Aug 02, 2015 2:56:27 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [resources/spring-config.xml]
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Person List : 
Person [pId=1, name=Achilles]
Person [pId=2, name=Hektor]
Person with Id 1 is Person [pId=1, name=Achilles]
Aug 02, 2015 2:56:28 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@78221c75: startup date [Sun Aug 02 02:56:27 IST 2015]; root of context hierarchy


2. Download the Source Code

Here we demonstrated how to configure and manage a Cassandra Data Repository using Spring Data.

Download
You can download the source code of this example here: CassandraSpringData.zip

Chandan Singh

Chandan holds a degree in Computer Engineering and is a passionate software programmer. He has good experience in Java/J2EE Web-Application development for Banking and E-Commerce Domains.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button