Mostrando postagens com marcador cassandra orm. Mostrar todas as postagens
Mostrando postagens com marcador cassandra orm. Mostrar todas as postagens

domingo, 21 de julho de 2013

Novo Easy-Cassandra 2.0.0 Beta




    O Cassandra, o banco de dados não relacional orientados à família de colunas, é um banco feito para trabalhos de alta performance, alta escalabilidade horizontal além de ser tolerante a falhas. Uma das grandes vantagens de sua arquitetura de escalabilidade horizontal é que se pode fazer com que cresça o número de nós a partir de uma alta demanda e diminuir em períodos de pouco processamento, ideal para a plataforma nas nuvens tão comumente discutido. Em sua nova versão trouxe o novo Cassandra Query Language, CQL, a versão 3.0, que dentre suas melhorias está no trabalho de coleções, chaves compostas.


    Com tantas melhorias o único problema é a maneira de tirar proveito de maneira eficiente desses novos recursos, afinal o foco do desenvolvedor Java deve ser solução em OO e sobre tudo no objetivo da aplicação, regras de negócio, a ponto de que esse parser entre banco e negócio seja o menor possível. Com esse objetivo surgiu o Easy-Cassandra, seu foco é facilitar o desenvolver Java utilizar esses recurso sem em nenhum momento desfocar no objetivo e no negócio da aplicação. Nessa nova versão o framework ORM trouce as seguintes melhorias:


  •  Chave Composta
  • Mapeamento de coleções( java.util.List, java.util.Set, java.util.Map)
  • Reconhecimento automático dos demais cluters na conexão e trabalho de autobalanceamento.
  • Melhorias no levantamento da aplicação.
Criação do Schema, para o uso de keyspace diferente do passado.


    Nessa nova versão houve algumas quebras de retrocompatibilidades, isso deve ao uso do java Driver e de suas consultas totalmente focadas no CQL 3. Essa pequena quebra está apenas no modo em que é criado a classe ponte entre o cassandra e o seu objeto java já que as anotações de mapeamento continuam tendo como base as anotações do JPA 2.0.
     Como a ideia no futuro é que exista o banco MongoDB, foi criada a interface org.easycassandra.persistence.Persistence, assim os novos bancos de dados e o Cassandra terão esse contrato, assim será possível, trocando apenas a implementação, mudando o banco de dados não relacional.


  
public interface Persistence {

    boolean insert(Object bean);

    boolean delete(Object bean);

    boolean update(Object bean);

     List findAll(Class bean);

     T findByKey(Object key, Class bean);

    boolean deleteByKey(Object key, Class bean);

    boolean executeUpdate(String query);

}


A interface do cassandra org.easycassandra.persistence.cassandra.PersistenceCassandra, como todos os novos bancos compatíveis herda do Persistence e adiciona alguns pequenos recursos.
  
public interface PersistenceCassandra extends Persistence {

     List findByIndex(Object index, Class bean);

    Long count(Class bean);
}

    A classe responsável por gerar a implementação continua sendo a org.easycassandra.persistence.cassandra.EasyCassandraManager, mas ela se tornou um enum, sim isso mesmo um enum!, já que o objetivo é que ele seja único nada mais natural que o singleton natural cedido pela própria JVM. Só é necessário passar o host e o keyspace, caso não existe ele se responsabilizará por você. Para adicionar objetos mapeados no Cassandra basta usar o método addFamilyObject passando o .class, assim como no caso do keyspace, caso ele não existe ele se responsabilizará em criar ou alterar a column family, para o seu objeto.

Como base nisso o DAO base poderia ficar da seguinte maneira:

  
public class PersistenceDao {

    private static final String KEY_SPACE = "javabahia";
    private static final String HOST = "localhost";
    private PersistenceCassandra persistence;
    private Class baseClass;
    

    public PersistenceDao(Class baseClass) {
        this.baseClass = baseClass;
        persistence = EasyCassandraManager.INSTANCE.getPersistence(HOST, KEY_SPACE);
        EasyCassandraManager.INSTANCE.addFamilyObject(baseClass, KEY_SPACE);
        
    }

    public boolean insert(T bean) {
        return persistence.insert(bean);
    }

    public boolean remove(T bean) {
        return persistence.delete(bean);
    }

    public boolean removeFromRowKey(K rowKey) {
        return persistence.deleteByKey(rowKey, baseClass);
    }

    public boolean update(T bean) {
        return persistence.update(bean);
    }

    public T retrieve(Object id) {
     
        return   persistence.findByKey(id, baseClass);
    }

    public List listAll() {
        return persistence.findAll(baseClass);
    }

    public List listByIndex(Object index) {
        return persistence.findByIndex(index, baseClass);
    }

    public Long count() {
        return persistence.count(baseClass);
    }

    public boolean executeUpdateCql(String string) {
        return persistence.executeUpdate(string);
    }

}


    Uma outra estratégia seria a mudança de interface para a persistence, assim esse DAO seria para todos os bancos de dados nosql que o framework for sendo compatível. Uma vez pronto o nosso projeto base, vamos falar um pouco sobre o mapeamento dos objetos. Os desenvolvedores java que conhecem o JPA já estarão familiarizado como o modelo de mapeamento.
  
@Entity(name = "person")
public class Person implements Serializable {

    private static final long serialVersionUID = 3L;
    
    @Id
    private Long id;
    
    @Index
    @Column(name = "name")
    private String name;
    
    @Column(name = "born")
    private Integer year;
    
    
    @Enumerated
    private Sex sex;
    
    
    @Embedded
    private Address address;

//getter and setter
}

Assim os campos são:

  •  @Id serve para indicar que esse campo será a chave da linha.
  • @Enumerated indica que o campo é um enum.
  • @Embedded indica que existe um objeto complexo e este será embitudio na mesma linha.
  • @Index indica o índice, funciona como um segundo ID, assim será possível realizar busca a partir desse campo.
  • @Table ou @Entity indica que o objeto é mapeado e pega o nome da column family
  • @EmbeddedId indica que esse campo é um objeto complexo e nele está embutido as chaves da column family.

  

@Entity(name="linux")
public class LinuxDistribuition {

    @EmbeddedId
    private IdLinux id;
    
    @Column
    private String guy;
    
    @Column
    private String version;
    
    @Column(name="descriptions")
    private String descriptions;
//getter and setter
}

public class IdLinux {
    
    
    @Column
    private String name;
    
    @Column
    private String kernelVersion;
//getter and setter
}

Além desses campos essa nova versão trouxe novas anotações para se poder trabalhar com listas dentro do cassandra que são:

  • SetData indica que o campo é uma interface java.util.Set, é necessário informar o classeData na qual indica o tipo do objeto que terá no set.
  • ListData indica que o campo é uma interface java.util.List, é necessário informar o classeData na qual indica o tipo do objeto que terá na lista.
  • MapData indica que o campo é uma interface java.util.Map, é necessário informar a chave e o valor do map informando o classkey e classValue respectivamente.



Exemplos do uso dessa interação abaixo:


  
@Entity(name="resumebook")
public class Book {

    @Id
    @Column(name="booksname")
    private String name;
    
    @MapData(classKey=Long.class,classValue=String.class)
    private Map chapterResume;
//getter and setter
}


@Entity(name="shopping")
public class ShoppingList {

    @Id
    private String name;
    
    @Column(name="day")
    private Date day;
    
    @ListData(classData=String.class)
    @Column(name="frutis")
    private List fruits;
    
    @Column(name="storeName")
    private String storeName;
//getter and setter
}

@Entity(name="contact")
public class Contact implements Serializable {

    @Id
    @Column(name="id")
    private String name;
    
    
    @Column(name="emails")
    @SetData(classData=String.class)
    private Set emails;
//getter and setter
}


 Uma vez mapeado e com o DAO pronto o seu uso se torna muito fácil, já que as buscas são semelhantes a única diferença está no objeto mapeado e o retorno.
  
public class BookDAOTest {

 private PersistenceDao persistence=new PersistenceDao(Book.class);
    
    
    @Test
        public void insertTest() {
        Book book = getBook();
        Assert.assertTrue(persistence.insert(book));
    }


    private Book getBook() {
        Book book = new Book();
        book.setName("Cassandra Guide ");
        Map resumeChapter=new HashMap();
        resumeChapter.put(1l, "this chapter describes new resources in cassandra and improvements with CQL");
        resumeChapter.put(2l, "Understanding the architecture");
        resumeChapter.put(3l, "Installing DataStax Community");
        resumeChapter.put(4l, "Upgrading Cassandra");
        resumeChapter.put(5l, "Initializing a cluster");
        resumeChapter.put(6l, "Security");
        resumeChapter.put(7l, "Database design");
        resumeChapter.put(8l, "Using the database");
        resumeChapter.put(9l, "Database internals");
        resumeChapter.put(10l, "Configuration");
        resumeChapter.put(11l, "Operations");
        resumeChapter.put(12l, "Backing up and restoring data");
        resumeChapter.put(13l, "Cassandra tools");
        resumeChapter.put(14l, "Troubleshooting");
        resumeChapter.put(14l, "Troubleshooting");
        resumeChapter.put(15l, "References");
        book.setChapterResume(resumeChapter);
        return book;
    }
    
    
    @Test
    public void retrieveTest() {
        Book book=persistence.retrieve(getBook().getName());
        Assert.assertNotNull(book);
     
    }
    
    @Test
    public void removeTest() {
        persistence.remove(getBook());
        Assert.assertNull(persistence.retrieve(getBook().getName()));
        persistence.insert(getBook());
    }
    
}


public class ContactsDAOTest {
 private PersistenceDao persistence=new PersistenceDao(Contact.class);
    
    
    @Test
        public void insertTest() {
        Contact contacts = getContact();
        Assert.assertTrue(persistence.insert(contacts));
    }


    private Contact getContact() {
        Contact contacts = new Contact();
        contacts.setName("Shrek ");
        contacts.setCyte("far far away");
        contacts.setEmails(new HashSet());
        contacts.getEmails().add("shreck@shrek.org");
        contacts.getEmails().add("shreck@farfaraway.far");
        return contacts;
    }
    
    
    @Test
    public void retrieveTest() {
     Contact contact=persistence.retrieve(getContact().getName());
     Assert.assertNotNull(contact);
     
    }
    @Test
    public void removeTest() {
        persistence.remove(getContact());
        Assert.assertNull(persistence.retrieve(getContact().getName()));   
    }
    
}



public class ShoppingListDAOTest {

    private PersistenceDao persistence=new PersistenceDao(ShoppingList.class);
    
    
    @Test
    public void insertTest() {
        
        Assert.assertTrue(persistence.insert(getPolianaShoppingList()));
    }
    private ShoppingList getPolianaShoppingList() {
        ShoppingList shopping=new ShoppingList();
        shopping.setDay(new Date());
        shopping.setName("Poliana");
        shopping.setFruits(new LinkedList());
        shopping.getFruits().add("Orange");
        shopping.getFruits().add("beans");
        shopping.getFruits().add("rice");
        return shopping;
    }
    
    @Test
    public void retrieveTest() {
     ShoppingList list=persistence.retrieve(getPolianaShoppingList().getName());
     Assert.assertNotNull(list);
    }
    @Test
    public void removeTest() {
        ShoppingList list=persistence.retrieve(getPolianaShoppingList().getName());
        persistence.remove(list);
        list=persistence.retrieve(getPolianaShoppingList().getName());
        Assert.assertNull(list);
    }
    
}


    Outro recuso importante é que foi solicitado pela comunidade, abraços ao pessoal da Bern na Suiça, é a possibilidade de usar outro keyspace diferente do definido no persistence. Para isso basta usar o schema na anotação @Table como mostra o exemplo abaixo:
  
@Table(name="drink",schema="schemaA")
public class Drink implements Serializable {

     @Id
     private Long id;
     
     @Index
     @Column(name = "name")
     private String name;
     
     @Column(name = "flavor")
     private String flavor;



   A nova versão do Easy-Cassandra, 2.0.0, ainda está em fase beta, assim é necessário realizar mais testes, mas com isso tem noção do que vem está por vir. Uma das coisas legais do framework é pioneirismos do projeto, até então ele é o primeiro ORM do cassandra que utiliza os recursos do 100% CQL 3.0. Isso graças ao grande trabalho por parte da comunidade.




segunda-feira, 16 de abril de 2012

Lançada a versão 1.0.9 beta do apache Easy-Cassandra.




   Lançada a mais nova versão do framework que visa facilitar a persistência de objetos do apache Cassandra. Dentre as suas novidades está nas anotações, nessa versão estará usando as anotações do JPA. Outra novidade é o uso do recurso de JPQL, com isso se pode realizar querys com objetos e a ferramenta se encarregará de fazer a tradução para o Cassandra, para isso se utiliza a interface JCassandra que estende de javax.persistence.Query. A expectativa é que aumentar ainda mais a produtividade para o desenvolvimento.
JCassandra jCassandra=persistence.createJCassandra("select * from Person");
 List<Person> persons=jCassandra.getResultList();

tabela 1: exemplo usando o jpql no Easy-Cassandra



Conforme dito acima as anotações foram adaptadas conforme mostra a tabela 2.

Easy-Cassandra 1.0.8
Easy-Cassandra 1.0.9 (Com JPA anotação)
org.easycassandra.annotations.ColumnFamilyValue
javax.persistence.Entity
org.easycassandra.annotations.ColumnValue
javax.persistence.Column
org.easycassandra.annotations.EmbeddedValue
javax.persistence.Embedded
org.easycassandra.annotations.EnumeratedValue
javax.persistence.Enumerated
org.easycassandra.annotations.KeyValue
javax.persistence.Id
org.easycassandra.annotations.KeyValue equals true
javax.persistence.GeneratedValue
org.easycassandra.annotations.IndexValue
org.easycassandra.annotations.Index
tabela 2: relação entre as anotações da versão 1.0.8 e 1.0.9 com anotação jpa.



   Também foi adicionado funcionalidade na anotação @Version do jpa, seu objetivo é verificar o tempo de inserção ou modificação do objeto.
@Entity(name = "autocount")
public class Count implements Serializable {

    private static final long serialVersionUID = 3L;
    
    @Id
    @GeneratedValue
    private BigInteger id;
    
  
    @Column(name = "name")
    private String name;
    
    @Version
    private Long timeStampLong;

    @Version
    private Date timeStampDate;
    
    @Version
    private Calendar timeStampCalendar;

//getter and setter
}

tabela 3: Usando a anotação version



   Para demonstrar novos recursos do framework será feito um exemplo de álbuns musicais que possa ser chamados em várias plataformas, para isso será usado web services. Para realizar esse exemplo será utilizado o java EE 6. Como o foco desse artigo não será o java EE 6, não entraremos em detalhes do mesmo. Após modelar e realizar as anotações com o jpa nossa classe ficará como mostra a tabela4.

@XmlRootElement
@Entity
public class Album implements Serializable{
@Id
private Long id;
@Column(name="nameOfAlbum")
private String name;
@Column
private String style;
@Column
private Calendar release;
@Column
private Double price;
@Embedded
private Artist artist;
//getter and setter
}
@XmlRootElement
public class Artist implements Serializable{
/**
* name of the artist
*/
@Column(name="nameOfArtist")
private String name;
/**
* was born
*/
@Column
private String country;
@Enumerated
private Sex sex;
//getter and setter
}

@XmlRootElement
public enum Sex {
MALE,FAMALE
}
tabela 4: classe com anotações jpa para o Easy-Cassandra



   Uma vez pronta a classe de anotação o que será feito agora é recurso para o rest, uma coisa que vale salientar é que a inteface JCassandra estende da interface javax.persistence.Query, assim se pode estar a utilizando a interface Query (interessante para quem já está acostumado com o uso do jpa). Sendo que nem todas os métodos dessa interface estão implementados.

Assim realizando as chamadas com o novo recurso de jpql no Cassandra ficará de acordo mostra a tabela 5. Vale salientar como é feito para o Easy-Cassandra gerenciar a classe. Esse processo é realizado sem a necessidade do uso do xml, para isso é usado do método addFamilyObjec na Classe EasyCassandraManager. É necessário que a classe seja adicionada antes de se criar um jpql da respectiva classe. No nosso exemplo ele será feito na classe PersistenceManagement tão logo uma conexão para o cassandra for criada, como mostra a tabela 5.


@ApplicationScoped
public class PersistenceManagement {
@Produces
private Persistence persistence;
@Inject
public void init(){
persistence=EasyCassandraManager.getPersistence("javabahia", "localhost", 9160);
EasyCassandraManager.addFamilyObject(Album.class);
}
}

@RequestScoped
public class PersistenceService {

@Inject    
 private Persistence persistence;
   
    public List<Album> findAllAlbum() {
        Query query=persistence.createJCassandra(" select * from Album");
        return query.getResultList();
    }

    public Album findById(Long id) {
        Query query=persistence.createJCassandra(" select * from Album where id =:id");
        query.setParameter("id", id);
        return (Album) query.getSingleResult();
        
    }

    public boolean save(Album album) {
      return  persistence.insert(album);
    }

    public void remove(Long id) {
        persistence.deleteByKeyValue(id, Album.class);
    }

    public String update(Long id, String name, String style, Double price,String nameOfArtis,String country) {
       StringBuilder query=new StringBuilder();
     
       
        boolean updatable=createMethod(query, name, style, price, country, nameOfArtis);
     
       if(!updatable){
            return "nothing is update";
       }
       
       Query jCassandra=persistence.createJCassandra(query.toString());
       setParameter(name, jCassandra, style, price, nameOfArtis, country);   
       jCassandra.setParameter("id", id);
       return jCassandra.executeUpdate()==1?"executed with sucess":" error in update ";
     
    }

    private void setParameter(String name, Query jCassandra, String style, Double price, String nameOfArtis, String country) {
        if(!isnull(name)){
        jCassandra.setParameter("name", name);
     }
     if(!isnull(style)){
  
      jCassandra.setParameter("style", style);
     }
     if(!isnull(price)){
       jCassandra.setParameter("price", price);
     }
     if(!isnull(nameOfArtis)){
    
      jCassandra.setParameter("artist", nameOfArtis);
     }
     if(!isnull(country)){
       jCassandra.setParameter("country", country);
     }
    }

    private boolean createMethod(StringBuilder query, String name, String style, Double price, String country, String nameOfArtis) {
        String conecion="";
        boolean updatable=false;
        query.append("update Album set ");
        if(!isnull(name)){
            query.append(conecion);
            query.append(" name =:name ");
            updatable=true;
            conecion=" , ";
        }
        if(!isnull(style)){
        query.append(conecion);
            query.append(" style =:style ");
            updatable=true;
            conecion=" , ";
        }
        if(!isnull(price)){
            query.append(conecion);
            query.append(" price =:price ");
            updatable=true;
        }
        
          if(!isnull(country)){
        query.append(conecion);
            query.append(" artist.country =:country ");
            updatable=true;
            conecion=" , ";
        }
        if(!isnull(nameOfArtis)){
            query.append(conecion);
            query.append(" artist.name =:artist ");
            updatable=true;
        }
        
        query.append(" where id =:id ");
        return updatable;
    }
   
    
    
    private boolean isnull(Object object){
    
        return object==null;
    }
    
}



tabela 5: realizando um jpql no cassandra



Uma vez implementados as querys será feito agora as chamadas agora será criado o recurso conforme mostra a tabela 6.

@Path("/album")
@RequestScoped
public class AlbumResource {
@Inject
private PersistenceService persistenceService;

@GET
@Produces(MediaType.TEXT_XML)
public List getProdutos() {
return persistenceService.findAllAlbum();
}
@Path("{id}")
@GET
@javax.ws.rs.Produces(MediaType.TEXT_XML)
public Album getAlbum(@PathParam("id") long id) {
return persistenceService.findById(id);
}

@Path("update/{id}")
@GET
@javax.ws.rs.Produces(MediaType.TEXT_PLAIN)
public String updateAlbum(@PathParam("id") Long id ,@QueryParam("name") String name,@QueryParam("style") String style,@QueryParam("price") Double price,@QueryParam("artist") String nameOfArtis,@QueryParam("country") String country) {

return persistenceService.update(id,name,style,price,nameOfArtis,country);
}
@POST
@Consumes(MediaType.TEXT_XML)
@Produces(MediaType.TEXT_PLAIN)
public String addAlbum(Album album) {
boolean sucess=persistenceService.save(album);
if(sucess){
return album.getName() + " added!";
}
return album.getName() + " not added!";
}



@Path("{id}")
@DELETE
@Produces(MediaType.TEXT_PLAIN)
public String removeAlbum(@PathParam("id") Long id) {
persistenceService.remove(id);
return "Album removed.";
}
}
tabela 6: criando um servidor  rest com o JAX-RS



   Uma das maneiras de se realizar os testes é utilizando o poster, um plugin para o firefox, que estará disponível nos links. Com ele se poderá realizar todos os testes, inclusive aqueles que envolvam o post e remove. É possível realizar alguns testes já no navegador:

Lista de álbum
Lista o álbum com o id 1
Lista o álbum com o id N
Insere ou atualiza um álbum com id igual a 12 com o nome, país Brasil, estilo eletrônico, preço 23 e o artista eu
tabela 7: exemplos de serviços com o rest



   Com isso foi demonstrado as novidades da nova versão do Easy-Cassandra, versão 1.0.9, que visa facilitar a vida do desenvolvedor. Foi demonstrado as mudanças para anotações típicas do jpa, novo recurso que recupera o timestamp da linha além do uso do JPQL por parte do framework. Muito ainda se tem de melhorar na ferramenta, mas com ajuda da comunidade isso será possível.


Link:
Exemplo servidor rest (AlbumServerRest.rar): https://github.com/otaviojava/Easy-Cassandra/downloads

Download o código e a documentação para a versão 1.0.9 ( documento 03): https://github.com/otaviojava/Easy-Cassandra/downloads


sexta-feira, 2 de março de 2012

Usando Easy-Cassandra 1.0.8 com maven



       Lançada a mais nova versão do framework Easy-Cassandra seu objetivo é estar facilitando a comunicação entre Apache Cassandra e sua aplicação em java. Com ele é possível esta criando, atualizando, recuperando ou deletando os seus objetos java de uma maneira bastante simples, para isso basta apenas realizar anotações na classe e nos campos.

CARACTERÍSTICAS



  • Uma espécie de ORM para o Cassandra
  • Precisa apenas de anotações na classe para persistir informações
  • Persiste muito objetos java de uma maneira bastante fácil
  • Escreve e ler no Cassandra com Level Consistency.
  • O primeiro compatível com versões acima do Cassandra 0.8
  • Compatível com CQL 2.0
  • O primeiro a usar invokedynamic ao invés de Reflection
  • Sob a licença Apache versão 2.0
  • Suporte aos seguintes objetos


As novidades nessa versão:


  • Criação de Famílias de colunas e índices secundários em tempo de execução
  • Suporte ao CQL 2.0
  • suporte a chamada de chaves com 'in'




    Para demonstrar essa nova versão será apresentado um exemplo prático com uma aplicação simples. Essa aplicação terá o objetivo de armazenar informações da média de renda dos brasileiros agrupados por CEP, a ideia seria saber quanto é gerado em reais e o número de entidades comerciais ( padarias, mercados, mercadinhos, açougues etc.) que geram esse valor em um determinado local, CEP. Assim será armazenado aproximadamente 640 mil informações a cada levantamento de estudo.
Cada requisição para o estudo terá as seguintes informações:


  • Código do Lote
  • Quantidade de pessoas calculadas no setor CEP
  • Valor computado
  • Cidade
  • Logradouro
  • Bairro
  • Cep
  • Tipo do logradouro
  • Estado
  • Sigla


    Para armazenar essas informações será utilizado o banco nosql Cassandra que é:


  1. Altamente confiável:
    Utilizado por diversas empresas entre elas Cisco, Reddit, Twitter. O maior cluster conhecido do Cassandra possui mais de 300 tb em 400 máquinas .
  2. Tolerante a falhas :
    Os dados são replicados automaticamente para múltiplos nós para a tolerância a falhas.
  3. Descentralizado :
    Já que não existe ponto de falha nem gargalhos de rede. Já que cad nós é idêntico .
  4. Configurável:
    Se pode escolher de uma maneira bastante simples se será uma atualização síncrona ou assíncrona além de possuir Hinted Handoff e Read Repair .
  5. Escalável :
    Com ele tanto a escalabilidade horizontal e vertical poderão ser feitas de uma maneira bastante simples. Além de adicionar novas máquinas podem ser adicionadas sem tempo de interrupção .
  6. Durável :
    Foi projeto para não perder informações mesmo quando vários nós falham.


    Para facilitar o desenvolvimento será utilizado o Easy-Cassandra que funcionará como uma camada de acima do Thrift facilitando as chamadas para o Cassandra, aumentando a produtividade além de deixar o código mais limpo. Para seu funcionamento é necessário baixar a lib do framework além de suas dependências (mais informações no final do artigo). Para facilitar o gerenciamento dessas lib nesse exemplo será utilizado o maven, para ter acesso o projeto é necessário adicionar o repositório além da tag da lib conforme mostra a tabela 1.



Tabela1: chamada do repositório e chamada da lib do Easy-Cassandra

Cada requisição representará uma linha no Cassandra que pode varia o seu tamanho de linha por linha. Assim mapeando as requisições com as anotações ficará de acordo com a tabela 2.


@ColumnFamilyValue(name = "controle")
public class ControleRenda implements Serializable {

@KeyValue(auto = true)
private Long id;
@EmbeddedValue
private Endereco endereco;
@ColumnValue(name = "valor")
private Double valor;
@ColumnValue(name = "quantidade")
private Long quantidade;
//getter and setter
}

public class Endereco implements Serializable {

@ColumnValue(name="cidade")
private String cidade;
@ColumnValue(name="logradouro")
private String logradouro;
@ColumnValue(name="bairro")
private String bairro;
@IndexValue
@ColumnValue(name="cep")
private String cep;
@ColumnValue(name="tp_logradouro")
private String tp_logradouro;
@ColumnValue(name="estado")
private String estado;
@ColumnValue(name="sigla")
private String sigla;
// getter and setter
}

Tabela 2: Mapeamento das classes para o controle de renda por cep


    Ao ver a tabela 2 na classe Endereço existe a anotação @IndexValue no campo cep, essa anotação faz com que esse campo seja um índice secundário, um campo que além da chave pode recuperar informações dentro da linha. Com isso nessa linha além do código de controle ( coluna chave) a linha pode ser recuperada pelo cep ( campo chave secundária).
Para simular essas requisições foi utilizado um arquivo texto com aproximadamente 640 mil linhas. Cada linha possui as informações separado por pipe '|'.
Para rodar o nosso exemplo é necessário que o Cassandra esteja rodando já que tanto a família de colunas tanto a chave secundária serão criados em tempo de execução graças ao um recurso da nova versão.


create keyspace renda;



    Assim basta executar a aplicação e todas as informações estarão persistiradas no cassandra. De fato existe inúmeras maneiras de aumentar a performance do cassandra (configurando o GC, configurando o heap, aumentando o número de nós e clusters, etc.), mas nesse exemplo foi mostrado usando os recursos padrões.
Nesse artigo foi demonstrado um exemplo prático utilizando o Easy-Cassandra 1.0.8 junto com o maven, realizando um programa simples com 640 requisições. Foi demonstrado alguns novos recursos como a criação da família de coluna e a chave secundária em tempo de execução.


Referências:




Documentação, lib e código exemplo (Maven_Example.rar): https://github.com/otaviojava/Easy-Cassandra/downloads