Recentemente foi lançada a nova versão do Easy-Cassandra - versão 2.0. - e dentre as novidades podemos citar:

  • Refatoração nos construtores das fábricas de sessão;
  • QueryBuilder (InsertBuilder, UpdateBuilder, DeleteBuilder, SelectBuilder e BatchBuilder);
  • Maior velocidade na leitura e escrita;
  • Suporte nos processos assíncronos;
  • Maior suporte ao Cassandra com Spring-Data.

Nota: Se você não conhece o projeto, não deixe de conferir esse artigo e entender o que é o Easy Cassandra.

Um ponto importante é que para facilitar a configuração foi criada a classe ClusterInformation, que é passada no parâmetro, de maneira simples, deixando o código mais limpo, afinal, sobrecarga de construtores não é uma boa prática. Um exemplo de configurações pode ser visto na Listagem 1.

Listagem 1. Classe ClusterInformation

ClusterInformation clusterInformation = ClusterInformation.create()
                .addHost(HOST)
                .withDefaultKeySpace(KEY_SPACE).withUser(USER).withPassword(PASS);
        easyCassandraManager = new EasyCassandraManager(clusterInformation);

Dessa forma, a configuração para usar o Spring no Cassandra também mudou. Veja a Listagem 2.

Listagem 2. Configuração para o Cassandra

<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.easycassandra.persistence.cassandra.spring" />

<bean id = "clusterInformation" class="org.easycassandra.persistence.cassandra.ClusterInformation">
            <property name="keySpace" value="campus" />
            <property name="hosts">
                        <list>
                                   <value>localhost</value>
                        </list>
            </property>
</bean>

<bean id="cassandraFactory" class="org.easycassandra.persistence.cassandra.spring.CassandraFactoryAnnotation">
            <constructor-arg name="clusterInformation" ref="clusterInformation" />
            <property name="annotatedClasses">
                        <list>
                                   <value>org.easycassandra.persistence.cassandra.spring.entity.Contact</value>
            <value>org.easycassandra.bean.model.Step</value>
            <value>org.easycassandra.bean.model.Weight</value>
                        </list>
            </property>
</bean>

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

</beans>

A melhoria mais marcante nessa versão são os recursos dos QueryBuilders, que são maneiras muito mais fácil de fazer interações com o Cassandra com configurações adversas de uma maneira mais simples. Com esses recursos, é possível definir o nível de consistência, definir o timeStamp e quais campos serão manipulados.

Nota: Para quem tem dúvidas e problemas com o timestamp, não podem deixar de dar uma olhada nesse tópico que mostra como subtrair hora do timestamp.

Veja na Listagem 3 como inserir valores a partir da chave.

Listagem 3. Simples exemplo inserindo valores a partir da chave

SimpleID id = new SimpleID();
   id.setIndex(ONE_HUNDRED_THIRTY);
   id.setKey(ONE_HUNDRED_THIRTY);
   UpdateBuilder<SimpleQueryBuilder> update = template.updateBuilder(SimpleQueryBuilder.class, key);
   update.put("map", "name", "otavioMap").value("value", TEN_DOUBLE).execute();

Na Listagem 4 vemos toda a query de atualização.

Listagem 4. Query de atualização

UpdateBuilder<SimpleQueryBuilder> update = persistence.updateBuilder(SimpleQueryBuilder.class);
 update.whereEq(Constant.KEY, Constant.ONE).whereEq(Constant.INDEX, Constant.ONE).addList("list", "otavioList").execute();

Na Listagem 5 temos o código de criação da atualização assíncrona.

Listagem 5. Executando uma atualização assincronamente

UpdateBuilder<SimpleQueryBuilder> update = persistence.updateBuilder(SimpleQueryBuilder.class);
 update.whereEq(Constant.KEY, Constant.ONE).whereEq(Constant.INDEX, Constant.ONE).value("value", 12D).executeAsync(new ResultAsyncCallBack<Boolean>() {
    @Override
    public void result(Boolean bean) {
        // do some action
    }
});

Nas Listagens 6 e 7 veremos a codificação do processo de inserção do nosso exemplo.

Listagem 6. Realizando inserção

InsertBuilder<SimpleQueryBuilder> insert= persistence.updateBuilder(SimpleQueryBuilder.class);
Set<String> set = new HashSet<>();
set.add("Linda");
Map<String, String> map = new HashMap<>();
map.put("love", "Otavio and Poliana");
insert.value(Constant.KEY, Constant.ONE_HUNDRED).value(Constant.INDEX,
            Constant.ONE_HUNDRED).value(Constant.LIST_COLUMN, Arrays.asList("Poliana", "Otavio", "Love")).value(Constant.SET_COLUMN, set).value("map", map).execute();

Listagem 7. Realizando inserção de modo assíncrono

SimpleID id = new SimpleID();
  id.setIndex(ONE_HUNDRED_TWO);
  id.setKey(ONE_HUNDRED_TWO);
  SimpleBean simpleBean = new SimpleBean();
  simpleBean.setId(id);
  simpleBean.setValue(VALUE);
  InsertBuilder<SimpleQueryBuilder> insert2 = persistence.updateBuilder(simpleBean);
  insert2.executeAsync((new ResultAsyncCallBack<Boolean>() {
  @Override
  public void result(Boolean bean) {
      // do some action
  }
  });

Na Listagem 8 vemos o código de duas query: a primeira query remove todas as colunas a partir da chave, e a segunda query remove apenas os campos map, list e set.

Listagem 8. Querys de remoção

DeleteBuilder<SimpleBean> delete = persistence.deleteBuilder(SimpleQueryBuilder.class);
  delete.whereEq(Constant.INDEX, ONE_HUNDRED_TWO).whereEq(Constant.KEY, ONE_HUNDRED_TWO).execute();
  DeleteBuilder<SimpleBean> delete2 = persistence.deleteBuilder(SimpleQueryBuilder.class,"map", "list", "set"); //Delete specific columns
  delete2 .whereEq(Constant.INDEX, ONE_HUNDRED_TWO).whereEq(Constant.KEY, ONE_HUNDRED_TWO).execute();

Na Listagem 9 vemos o código da remoção assíncrona.

SimpleID id = new SimpleID();
   id.setIndex(ONE_HUNDRED_TWO);
   id.setKey(ONE_HUNDRED_TWO);

   DeleteBuilder<SimpleBean> delete2 = persistence.deleteBuilder(SimpleQueryBuilder.class, id);
   delete2.executeAsync((new ResultAsyncCallBack<Boolean>() {
   @Override
   public void result(Boolean bean) {
       // do some action
   }
   });

Na Listagem 10 realizamos o select em que o campo nome é igual a nome e o índice está em um, dois e três.

Listagem 10. Código select

SelectBuilder<SimpleQueryBuilder> select = persistence.selectBuilder(SimpleQueryBuilder.class);
select.eq("name", "name");
select.in("index", ONE, TWO, THREE);
List<SimpleQueryBuilder> result = select.execute();

Na Listagem 11 temos o código da execução da query assincronamente, em que o índice seja mais que três e seja ordenado de forma descendente no índice.

Listagem 11. Execução da query

SelectBuilder<SimpleQueryBuilder> select = persistence.selectBuilder(SimpleQueryBuilder.class);
select.eq(NAME, NAME).gt("index", THREE).asc(INDEX).executeAsync(new ResultAsyncCallBack<List<SimpleBean>>() {

        @Override
        public void result(List<SimpleBean> beans) {
          // do some thing
        }
    });

O Batch é um recurso do Cassandra e permite que se executem alterações no banco (inserção, atualização e remoção) de forma atômica. Dessa forma, pode-se enviar insert, updates e deletes como se fosse apenas uma requisição.

Na Listagem 12 temos o código de execução do processo de inserção, remoção e atualização de forma atômica com o BatchBuilder.

Listagem 12. Alterações no banco com BatchBuilder

DeleteBuilder<SimpleBean> delete = dao.deleteBuilder();
    delete.whereEq(Constant.INDEX, Constant.ONE_HUNDRED_TWO)
            .whereEq(Constant.KEY, Constant.ONE_HUNDRED_TWO);

    InsertBuilder<SimpleBean> insert = dao.insertBuilder();
    insert.value(Constant.KEY, Constant.ONE_HUNDRED).value(Constant.INDEX,
            Constant.ONE_HUNDRED);
    insert.value(Constant.LIST_COLUMN,
            Arrays.asList("Poliana", "Otavio", "Love"));

    UpdateBuilder<SimpleBean> update = dao.update();
    update.whereEq(Constant.KEY, Constant.ONE).whereEq(Constant.INDEX, Constant.ONE);
    update.addList("list", "otavioList");

    BatchBuilder batchBuilder = dao.batchBuilder();

    batchBuilder.addOperations(delete, insert, update);
    batchBuilder.executeAsync(new ResultAsyncCallBack<Boolean>() {
        @Override
        public void result(Boolean bean) {
            // do some action
        }
    });

Vale lembrar que recurso do Batch deve ser usado em casos específicos, já que distribuir as requisições entre os nós, no Cassandra, sempre será uma boa prática.

Referências

https://github.com/otaviojava/Easy-Cassandra/wiki/Builders

https://github.com/otaviojava/Easy-Cassandra/wiki