Uma das maiores barreiras para quem quer começar a usar novas tecnologias geralmente é a curva de aprendizado. Muitas vezes, ao iniciar um novo projeto, acabamos optando por usar o que já sabemos para evitar qualquer atrito logo no início.

Passei a maior parte de minha carreira trabalhando como desenvolvedor Java e, nos últimos anos, me apaixonei pela tecnologia JPA + Pé de mola + Lombok + Dados do Spring mas a única coisa que ainda me incomodava era o mapeamento de relacionamentos.

A JPA é conhecida por carregar dados desnecessários do banco de dados e, com o tempo, você é forçado a revisitar algumas de suas entidades para alterar alguns relacionamentos de EAGER para LAZY. Isso pode melhorar significativamente seu desempenho, pois você evitará muitos JOINS desnecessários, mas não é gratuito. Você terá que refatorar bastante para carregar esses novos objetos lazy sempre que necessário.

Esse padrão comum sempre me incomodou e fiquei muito feliz quando descobri que o Spring Data e o Couchbase podem se conectar (documento completo aqui). É simplesmente a melhor parte de dois mundos: posso programar como faria em um banco de dados relacional, mas ainda aproveitando toda a velocidade do Couchbase e o poder do N1QL. Vamos ver como configurar um projeto simples.

 

Configuração do Spring Data, do Spring Boot e do Couchbase

 

Pré-requisitos:

  • Presumo que você já tenha o Couchbase instalado. Se não tiver, por favor Faça o download aqui
  • Também estou usando o Lombok, portanto, talvez seja necessário instalar o plug-in do Lombok em seu IDE: Eclipes e IntelliJ IDEA

 

Primeiro, você pode clonar meu projeto:

ou simplesmente vá para Inicialização do Spring-Boot e adicione o Couchbase e o Lombok como dependências:

Observação: O Lombok não é uma dependência obrigatória, mas ajuda a reduzir significativamente sua base de código.

 

Agora, vamos definir a configuração do seu bucket no application.properties file:

E é isso! Você já pode iniciar seu projeto usando:

 

Mapeamento de uma entidade

Até o momento, nosso projeto não faz nada. Vamos criar e mapear nossa primeira entidade:

 

    • @Document: A anotação do Couchbase que define uma entidade, semelhante a @Entidade em JPA. O Couchbase adicionará automaticamente uma propriedade chamada _classe no documento para usá-lo como o tipo de documento.
    • @Data:  Anotação do Lombok, gerador automático de getters e setters
    • @AllArgsConstructor: A anotação do Lombok gera automaticamente um construtor usando todos os campos da classe, esse construtor é usado em nossos testes.
    • @NoArgsConstructor: A anotação do Lombok gera automaticamente um construtor sem argumentos (exigido pelo Spring Data)
    • @EqualsAndHashCode: Os métodos de anotação, geração automática de iguais e hashcode do Lombok também foram usados em nossos testes.
    • @NotNull: Sim, você pode usar o javax.validation com o Couchbase.
    • @Id: A chave do documento
    • @Campo:  As anotações do Couchbase, semelhantes a @Coluna

 

O mapeamento de entidades no Couchbase é realmente simples e direto, a maior diferença aqui é o @Campo que é usada de três maneiras diferentes:

  • Propriedade simples: Em casos como id, nome e companyId, o @Campo age de forma muito parecida com o @Coluna na JPA. Isso resultará em uma propriedade simples no documento:

  • Matrizes: No caso do phoneNumbers, isso resultará em uma matriz dentro do documento:

  • Entidades: Finalmente, no caso das áreas, @Campo age como um @ManyToOne a principal diferença é que você não é obrigado a mapear nada na entidade Area:

 

 

Repositórios

Seus repositórios serão muito parecidos com os repositórios padrão do Spring Data, mas com algumas anotações adicionais:

 

  • @N1qlPrimaryIndexed: Este anotação garante que o bucket associado ao repositório atual terá um índice primário N1QL
  • @ViewIndexed:  Isso anotação permite que você defina o nome do documento de design e o nome da visualização, bem como um mapa personalizado e uma função de redução.

No repositório acima, estamos estendendo CouchbasePagingAndSortingRepositoryque permite que você pagine suas consultas simplesmente adicionando um Paginável param no final da definição do método

Como ele é essencialmente um repositório, você pode aproveitar todos os Palavras-chave do Spring Data como Encontrar, Entre, IsGreaterThan, Como, Existeetc. Portanto, você pode começar a usar o Couchbase sem quase nenhum conhecimento prévio e ainda assim ser muito produtivo.

Como você deve ter notado, é possível criar N1QL mas com alguns detalhes de sintaxe:

  • #(#n1ql.bucket):  Use esta sintaxe para evitar a codificação do nome do bucket na consulta
  • #{#n1ql.selectEntity}: açúcar-sintaxe para SELECT * FROM #(#n1ql.bucket):  
  • #{#n1ql.filter}: syntax-sugar para filtrar o documento por tipo, o que tecnicamente significa class = 'myPackage.MyClassName' (_classe é o atributo adicionado automaticamente no documento para definir seu tipo quando você está trabalhando com o Couchbase no Spring Data )
  • #{#n1ql.fields} será substituído pela lista de campos (por exemplo, para uma cláusula SELECT) necessária para reconstruir a entidade.
  • #{#n1ql.delete} será substituído pela instrução delete from.
  • #{#n1ql.returning} será substituído pela cláusula de retorno necessária para reconstruir a entidade.

Para demonstrar alguns dos recursos interessantes do N1QL, vamos nos aprofundar um pouco mais em dois métodos do nosso repositório: findByPhoneNumber e findByCompanyAndAreaId:

 

findByPhoneNumber

No caso acima, estamos simplesmente procurando edifícios por números de telefone. Em um mundo relacional, normalmente seriam necessárias duas tabelas para realizar praticamente a mesma coisa. Com o Couchbase, podemos armazenar tudo em um único documento, o que torna o carregamento de um "edifício" muito mais rápido do que seria possível usando qualquer RDBMS.

Além disso, você pode acelerar ainda mais o desempenho da consulta adicionar um índice no atributo phoneNumbers.

 

findByCompanyAndAreaId

Na consulta acima, estamos basicamente tentando encontrar o nó raiz (Edifício) dando um nó filho aleatório (Área). Nossos dados são estruturados como uma árvore porque uma área também pode ter uma lista de outras áreas:

 

Esse tipo de consulta é uma das operações mais caras e complexas quando se trabalha com um banco de dados relacional; na maioria dos casos, você encontra o nó raiz manualmente ou usando uma consulta grande com UNIÃOs e CONECTADOS POR.

Aqui você pode resolver esse problema usando uma palavra-chave mágica chamada DENTRO.

 

Serviços

Por padrão, você injetará e usará seus repositórios em seus serviços como faria normalmente, mas poderá acessar adicionalmente os recursos específicos de repositórios do Couchbase usando o método getCouchbaseOperations()

 

Tudo em ação

 

O uso dos serviços é exatamente o que você espera:

 

Confira a classe de teste de integração BuildingServiceIntegrationTest para ver tudo em ação.

Se você tiver alguma dúvida, envie-me um tweet para @deniswsrosa ou faça uma pergunta em nosso fórum

 

Autor

Postado por Denis Rosa, defensor dos desenvolvedores, Couchbase

Denis Rosa é um Developer Advocate do Couchbase e mora em Munique, na Alemanha. Ele tem uma sólida experiência como engenheiro de software e fala fluentemente Java, Python, Scala e Javascript. Denis gosta de escrever sobre pesquisa, Big Data, IA, microsserviços e tudo o mais que possa ajudar os desenvolvedores a criar um aplicativo bonito, mais rápido, estável e escalável.

11 Comentários

  1. Este é um ótimo blog! Sou muito novo no Spring e no Spring boot. E estamos configurando o CouchBase. Tenho o CouchBase em execução localmente no meu computador, mas não encontrei nenhuma provisão para fornecer a senha do bucket. Por isso, quando estou executando meu aplicativo, ele está dando InvalidPasswordException: Passwords for bucket do not match.

    Você poderia me informar como posso resolver isso?

    1. Denis Rosa, defensor dos desenvolvedores, Couchbase novembro 30, 2018 em 2:16 am

      Oi Kn,

      A maneira mais fácil é criar um usuário com o mesmo nome do seu bucket e, em seguida, seguir este tutorial
      https://www.couchbase.com/couchbase-spring-boot-spring-data/

      Se quiser ter vários usuários acessando o mesmo bucket, será necessário implementar a classe AbstractCouchbaseConfiguration

      https://stackoverflow.com/questions/53177777/couchbase-6-0-springboot-invalidpasswordexception

  2. Sou novo no Couchbase e no Spring Data, implementação do Spring Boot. Estou usando a API de subdocumento de documento para atualizar, inserir e remover o subdocumento sem ler o documento inteiro. Posso codificar o caminho para o subdocumento e fazer operações de mutação diretamente no subdocumento. Uma das vantagens da API de subdocumento de documento é que posso atuar no subdocumento sem bloquear o documento inteiro (no meu caso de uso).

    Como posso fazer o mesmo usando o spring-data e o Spring boot. Vejo que a principal diferença é que o spring-data trabalha com consulta N1QL e POJO, enquanto a API de subdocumento de documento trabalha com Json.

    Referência à API do subdocumento do documento: https://docs.couchbase.com/java-sdk/2.7/subdocument-operations.html

  3. Denis Rosa, defensor dos desenvolvedores, Couchbase novembro 30, 2018 em 2:32 am

    Oi Muraic,

    Os subdocumentos geralmente são mais rápidos, pois você obtém o documento por sua chave. Entretanto, os dados do Spring são muito mais produtivos.

    Se você chamar yourRepository.getCouchbaseOperations().getCouchbaseBucket(), terá acesso ao objeto Bucket, que potencialmente é o que você está usando no momento.

  4. É possível se conectar via SSL e usar a criptografia de campo com o Spring Data Couchbase?

  5. Abhimanyu Mishra maio 21, 2019 em 8:06 am

    Olá Denis, sou muito novo em tecnologias de sistema aberto e estou tentando entender como seu projeto é executado. Instalei o couchbase, criei um documento e consigo ver o servidor em execução no console.

    No entanto, eu queria ver como o Java se integrará ao couchbase, então importei seu projeto e fiz a instalação limpa do mvn, mas estou recebendo erros de autenticação como :

    2019-05-21 20:14:31.776 WARN 9672 - [ cb-io-17-3] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Falha de autenticação.
    2019-05-21 20:14:31.777 WARN 9672 - [ cb-io-17-3] c.c.client.core.endpoint.Endpoint : Erro durante a reconexão:

    -05-21 20:14:31.778 WARN 9672 - [ cb-io-17-3] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Não foi possível conectar-se ao endpoint, tentando novamente com atraso de 4096 MILISECONDS:

    2019-05-21 20:14:35.922 WARN 9672 - [ cb-io-19-1] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Falha de autenticação.
    2019-05-21 20:14:36.020 WARN 9672 - [ cb-io-19-2] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Falha de autenticação.
    2019-05-21 20:14:36.021 WARN 9672 - [ cb-io-19-2] c.c.client.core.endpoint.Endpoint : Erro durante a reconexão:

    2019-05-21 20:14:36.029 WARN 9672 - [ cb-io-19-3] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Falha de autenticação.
    2019-05-21 20:14:36.030 WARN 9672 - [ cb-io-19-3] c.c.client.core.endpoint.Endpoint : Erro durante a reconexão:

    2019-05-21 20:14:36.362 WARN 9672 - [ cb-io-19-3] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Falha de autenticação.
    2019-05-21 20:14:36.363 WARN 9672 - [ cb-io-19-3] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Não foi possível conectar-se ao endpoint, tentando novamente com atraso de 32 MILISECONDS:

    Poderia me informar se estou perdendo alguma etapa? Preciso fazer alguma configuração com relação a trazer o servidor localhost do couchbase ou estou perdendo as dependências do couchbase / não tenho nenhuma ideia, por favor, informe.

  6. Abhimanyu Mishra maio 21, 2019 em 8:07 am

    Olá Denis, sou muito novo em tecnologias de sistema aberto e estou tentando entender como seu projeto é executado. Instalei o couchbase, criei um documento e consigo ver o servidor em execução no console.

    No entanto, eu queria ver como o Java se integrará ao couchbase, então importei seu projeto e fiz a instalação limpa do mvn, mas estou recebendo erros de autenticação como :

    2019-05-21 20:14:31.776 WARN 9672 - [ cb-io-17-3] c.c.client.core.endpoint.Endpoint : [null][KeyValueEndpoint]: Falha de autenticação.
    2019-05-21 20:14:31.777 WARN 9672 - [ cb-io-17-3] c.c.client.core.endpoint.Endpoint : Erro durante a reconexão:

    Poderia me informar se estou perdendo alguma etapa? Preciso fazer alguma configuração com relação a trazer o servidor localhost do couchbase ou estou perdendo as dependências do couchbase / não tenho nenhuma ideia, por favor, informe.

    1. Abhimanyu Mishra maio 21, 2019 em 11:42 am

      Não se preocupe, encontrei a solução :) mas terei mais dúvidas nos próximos dias...

      1. Denis Rosa, defensor dos desenvolvedores, Couchbase maio 23, 2019 em 8:44 am

        Publique suas perguntas no StackOverflow, posso respondê-las lá.

  7. Oi Rosa,
    Sou novato no Couchbase com dados do Spring, mas, com base no P&D, consigo fazer operações CRUD facilmente. Ainda assim, estou enfrentando um problema de "key":{"empty": "false"} ao armazenar o valor da lista.

    Você também descreveu acima que :-

    private List phoneNumbers = new ArrayList();

    e,

    Matrizes: No caso do phoneNumbers, isso resultará em uma matriz dentro do documento:

    assim : -
    {
    "phoneNumbers": ["phoneNumber1", "phoneNumber2"]
    }

    Mas ele sempre é salvo como: - "key":{"empty": "false"}.

    1. michael.reiche@couchbase.com agosto 6, 2020 em 11:58 am

      > Mas ele sempre é salvo como: - "key":{"empty": "false"}.

      Esse problema foi corrigido no spring-data-couchbase 4.0.2

      Saudações

Deixar uma resposta