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