O Spring é um framework open source cujo o objetivo sempre foi facilitar a vida do desenvolvedor Java, começou com os recursos para injeção de dependência e hoje atua em diversas atividades triviais para um programador. Entre elas podemos citar a parte social com o Spring social no twitter, facebook, segurança com o Spring security além do já inversão de controle e inversão de dependência. O foco desse pequeno post é falar sobre o Spring Data e seu trabalho com o banco não relacional Cassandra.

O Spring-data é um pequeno módulo ou plugin do Spring e tem como objetivo auxiliar nos processos triviais de persistência criando uma camada entre a base onde se encontra as informações e o seu código java. Dessa maneira é possível, efetuar ações na base, usando como estrutura para as informações, o POJO (simples e velho objetos em java). Dentro do Spring Data já existem diversos tipo de base de informações.

  • Bancos Relacionais com JPA e JDBC
  • BigData com Apache Hadoop
  • Data-Grid com GermFire
  • HTTP com Rest
  • NOSQL com MongoDB, Neo4J, Redis e Hbase

Uma das grandes vantagem do Spring Data é ser filho do Spring. Ele não precisa de um servidor Java EE, ou seja, ele pode rodar em um simples contêiner como o tomcat ou mesmo rodar sem o auxílio do servidor. Sua injeção funciona com auxílio de um arquivo xml, mas não necessariamente toda configuração é feita por lá, existem várias anotações que podem ajudar o desenvolvedor, no entanto, cabe apenas ao mesmo saber em qual momento é mais adequado usar cada um deles.

Com esse foco o Spring Data Cassandra tem o foco de criar uma camada de alto nível para o nosql Cassandra, assim é possível com estruturas de POJOs estabelecer uma conexão no banco e realizar as operações CRUD, tudo isso sem abrir mão da estrutura de dados já conhecida pelo desenvolvedor Java. O Spring Data Cassandra ainda não foi fechada, mas o Easy-Cassandra já possui integração com Spring, agora é possível utilizá-lo com a injeção de dependências do framework Java mais famoso do mundo.

A aplicação será realmente bastante simples seu objetivo será apenas criar uma informação e armazenar no banco, em seguida recuperar pelo id. O primeiro passo será a criação da entidade pessoa, ela terá os campos id, nome e ano, conforme mostra a tabela número1.


@Entity(name = "person") 
public class Person implements Serializable { 

    @Id 
    private UUID id; 
     
    @Index 
    @Column(name = "name") 
    private String name; 
    
    @Column(name = "born") 
    private Integer year;
//getter and setter

}
Listagem 1. Criando a entidade pessoa

Como pode ser visto os campos são anotados via JPA 2.0, o segundo passo é a criação do xml, é nele que conterá as configurações do banco de dados (host, porta, keyspace padrão, etc.). O próximo passo é a configuração e criação da fábrica de conexões para o Cassandra dentro do spring, isso é, o host, porta e o keyspace padrão, e as classes que serão mapeadas como mostra no arquivo xml abaixo.


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

<context:component-scan base-package="org.javabahia.cassandra.spring" />	
<bean id="cassandraFactory" 
class="org.easycassandra.persistence.cassandra.spring.CassandraFactoryAnnotation">
	<constructor-arg name="host" value="localhost" />
	<constructor-arg name="keySpace" value="spring" />
	<property name="annotatedClasses">
		<list>
			<value>org.javabahia.cassandra.spring.entity.Person</value>
		</list>
	</property>
</bean>	

<bean id="cassandraTemplate" 
class="org.easycassandra.persistence.cassandra.spring.SimpleCassandraTemplateImpl" >
	<constructor-arg name="factory" ref="cassandraFactory" />
</bean>

</beans> 
Listagem 2. Configuração do Spring-Data, informando as configurações do Banco (host, porta, nesse caso a padrão, e o keySpace) além de criar o Template Cassandra

Com a fábrica de conexões do cassandra é possível retornar uma sessão, a via de comunicação do Cassandra com a aplicação Java, além disso será criado o CassandraTemplate, uma api de alto nível que consegue realizar a comunicação Cassandra sua aplicação a partir de um simples POJO, desse modo é possível realizar a operação CRUD de uma maneira bastante simples, o código abaixo mostra a interface do Cassandra template.


public interface CassandraTemplate{
    <T> T save(T entity);
    <T> Iterable<T> save(Iterable<T> entities);
    <T> void delete(T entity);
    <T> void delete(Iterable<T> entities);
    <K> void delete(K key, Class<?> entity);
    <K,T> void delete(Iterable<K>  keys, Class<T> entity);
    <T> void deleteAll(Class<T> entity);
    <T> T update(T entity);
    <T> Iterable<T> update(Iterable<T> entities);
    <T,K> T findOne(K key, Class<T> entity);
    <T,K> List<T> findAll(Iterable<K> keys, Class<T> entity);
    <T> List<T> findAll(Class<T> entity);
    <T,I> List<T> findByIndex(String columnName,I index,Class<T> entity);
    <K,T>boolean exist(K key, Class<T> entity);
    void executeUpdate(String query);
Listagem 3. Operações que podem ser realizadas com o seu Objeto

Além do CassandraTemplate existe o CassandraRepository, essa classe abstrata implementa o CrudRepository do SpringData, com ela é necessário apenas implementar o método que retornará o CassandraTemplate, conforme mostra a tabela abaixo.


@Repository("personRepository")
public class PersonRepository extends CassandraRepository<Person, UUID>{

	
	@Autowired
	private CassandraTemplate cassandraTemplate;
	
	@Override
	protected CassandraTemplate getCassandraTemplate() {
		return cassandraTemplate;
	}

}
Listagem 4. Criando o repositório para a classe Person

Como o CassandraReporitory implementa a classe base de operações do Spring todas as suas operações estarão disponíveis para serem utilizadas com o Cassandra.


public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> { 
	<S extends T> S save(S entity); 

	<S extends T> Iterable<S> save(Iterable<S> entities); 

	T findOne(ID id); 

	boolean exists(ID id); 

	Iterable<T> findAll(); 

	Iterable<T> findAll(Iterable<ID> ids); 

	long count(); 

	void delete(ID id); 

	void delete(T entity); 
	void delete(Iterable<? extends T> entities); 

	void deleteAll(); 
}
Listagem 5. Interface CrudRepository do Spring Data que é implementada pela classe abstrata CassandraRepository

Realizado as configurações o próximo passo é executar o projeto como mostra o código a seguir:


public class App 
{
    public static void main( String[] args )
    {
    	@SuppressWarnings("resource")
		ApplicationContext ctx = new GenericXmlApplicationContext("SpringConfig.xml");
    	
    	PersonRepository personService=ctx.getBean(PersonRepository.class);
    	
    	UUID uuid=UUID.randomUUID();
    	Person person=new Person();
    	person.setId(uuid);
    	person.setName("Otávio Santana");
    	person.setYear(25);
    	
    	personService.save(person);
    	
    	
    	Person otavio=personService.findOne(uuid);
    	System.out.println(otavio.getName());
    	
    	
    }
}
Listagem 6. Rodando o Simples Projeto, salvando e recuperando a informação

Com isso foi demonstrado o conceito do Spring Data e o seu funcionamento com o Cassandra utilizando o Easy-Cassandra, o intuito criar uma interface padrão para que todos os modelos de persistência a utilizem dentro do Spring é um grande e importante passo para utilizar uma nova base ou modelo de dados não haja impacto dentro do Spring, mas é muito importante salientar que mesmo que vários bancos utilizem essa interface é importante considerar uma nova modelagem, já que diferente dos bancos relacionais, a mudança de um banco NOSQL pode significar a mudança estrutura de armazenamento.