Cassandra Play :Kundera ORM

by Vivek Mishra


If need more information on cassandra, please visit :Cassandra In brief, Kundera is an ORM based solution over Cassandra.

Kundera provides you a way to map your existing java objects over Nosql(e.g. Cassandra,HBase,MongoDB).

Let’s proceed with example, I am taking a super column family example to demonstrate Kundera:

Post is a super column family and can be described as:
Post:
column_type:Super
Subcomparator_type: UTF8
Default_validation_class: UTF8

Post Entity:
@Entity
@Table(name = "Posts", schema = "Blog")
public class Post
{

/** The permalink. */
@Id
// row identifier
String permalink;

@Embedded
private PostData data;

@Embedded
private AuthorDetail author;


}

You need to generate getters and setters for the above fields.

Kundera is JPA compliant annotation based solution. So Post is annotated with @Entity.

At next line declaration @Table(name = “Posts”, schema = “Blog”) :
name = “Posts” represents SuperColumnFamily “Posts” and schema=”Blog” represents “Blog” keyspace .

You must have noticed @Embedded annotation marked over PostData. Well PostData is a superColumn defined within Posts and as a POJO it is defined as follows:

package com.impetus.kundera.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Embeddable;

import org.apache.commons.lang.builder.HashCodeBuilder;

@Embeddable
public class PostData
{
/** The title. */
@Column(name = “title”)
public String title;

/** The body. */
@Column(name = “body”)
public String body;

/** The created. */
@Column(name = “created”)
public Date created;

/**
*
*/
public PostData()
{
}

/**
* @return the title
*/
public String getTitle()
{
return title;
}

/**
* @param title
* the title to set
*/
public void setTitle(String title)
{
this.title = title;
}

/**
* @return the body
*/
public String getBody()
{
return body;
}

/**
* @param body
* the body to set
*/
public void setBody(String body)
{
this.body = body;
}

/**
* @return the created
*/
public Date getCreated()
{
return created;
}

/**
* @param created
* the created to set
*/
public void setCreated(Date created)
{
this.created = created;
}

@Override
public int hashCode()
{
return HashCodeBuilder.reflectionHashCode(this);
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append(“Post [title=”);
builder.append(title);
builder.append(“, body=”);
builder.append(body);
builder.append(“, created=”);
builder.append(created);
builder.append(“]”);
return builder.toString();
}

}

Similarly AuthorDetail is another SuperColumn defined as:
package com.impetus.kundera.entity;

import javax.persistence.Column;
import javax.persistence.Embeddable;

import org.apache.commons.lang.builder.HashCodeBuilder;

@Embeddable
public class AuthorDetail
{
/** The author. */
@Column(name = “authorname”)
public String name;

@Column(name = “email”)
public String email;

public AuthorDetail()
{
}

/**
* @return the author
*/
public String getAuthor()
{
return name;
}

/**
* @param author
* the author to set
*/
public void setAuthor(String author)
{
this.name = author;
}

/**
* @return the email
*/
public String getEmail()
{
return email;
}

/**
* @param email
* the email to set
*/
public void setEmail(String email)
{
this.email = email;
}

@Override
public int hashCode()
{
return HashCodeBuilder.reflectionHashCode(this);
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append(“, [author=”);
builder.append(name);
builder.append(“, email=”);
builder.append(email);
builder.append(“]”);
return builder.toString();
}
}

CRUD Operation Using Kundera over Posts:
First is you need to define your own persistence.xml with something like this:

<persistence-unit name="cassandra">
<provider>com.impetus.kundera.ejb.KunderaPersistence</provider>
<properties>
<property name="server.config" value="C:/Cassandra/cassandra-0.7.6/conf  /cassandra.yaml"/>
<property name="kundera.nodes" value="localhost"/>
<property name="kundera.port" value="9160"/>
<property name="kundera.keyspace" value="Blog"/>
<property name="kundera.dialect" value="cassandra"/>
<property name="kundera.client" value="Pelops"/>
<property name="kundera.cache.provider_class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider"/>
</properties>
</persistence-unit>

Next is to hold an instance of EntityManager as:
Configuration conf = new Configuration();
EntityManager manager = conf.getEntityManager(persistenceUnitName);

where persistenceUnitName is the one pointing to Cassandra.

Persist :

Post post = new Post();
String key = System.currentTimeMillis() + “-post”;
AuthorDetail authorDetail = new AuthorDetail();
PostData data = new PostData();
data.setTitle(“Vivek”);
post.setPermalink(key);
data.setBody(“KunderaPlay”);
authorDetail.setAuthor(“vivek”);
authorDetail.setEmail(“impetus@impetus.com”);
post.setAuthor(authorDetail);
post.setData(data);
manager.persist(post);

Find:
Post post_db = manager.find(Post.class, key);

Search via Sql Query:
String sql = "Select p.body from Post p where p.title like :tiitle";
Query query = manager.createQuery(sql);
query.setParameter("tiitle", "Vivek");
List posts = query.getResultList();

List of posts will only hold value for specified superColumn field. Which means it will only retrieve Posts super column and AuthorDetails will be have all values as null.

Thus Kundera also provides Secondry Index Support over Cassandra.

It is really easy programming with kundera over NoSql.

More information on Kundera can be found here

Kundera-Examples are also present at