Um Guia para Eclipse JNoSQL

Um Guia para Eclipse JNoSQL

1. Visão geral

EclipseJNoSQL é um conjunto de APIs e implementações quesimplify the interaction of Java applications with NoSQL databases.

Neste artigo, aprenderemos como instalar e configurar o JNoSQL para interagir com um banco de dados NoSQL. Vamos trabalhar com a camada de comunicação e mapeamento.

2. Camada de comunicação Eclipse JNoSQL

Tecnicamente falando, a camada de comunicação consiste em dois módulos:Diana API and a driver.

While the API defines an abstraction to NoSQL database types, the driver provides implementations for most known databases.

Podemos comparar isso com a API JDBC e o driver JDBC em bancos de dados relacionais.

2.1. API Eclipse JNoSQL Diana

Simplificando, existem quatro tipos básicos de bancos de dados NoSQL: Key-Value, Column, Document e Graph.

E a API Eclipse JNoSQL Diana define três módulos:

  1. valor-chave-diana

  2. coluna diana

  3. diana-document

O tipo de gráfico NoSQL não é coberto pela API, porque já é coberto porApache ThinkerPop.

A API é baseada em um módulo principal, diana-core, e define uma abstração para conceitos comuns, como Configuração, Fábrica, Gerente, Entidade e Valor.

Para trabalhar com a API, precisamos fornecer a dependência do módulo correspondente ao nosso tipo de banco de dados NoSQL.

Assim, para um banco de dados orientado a documentos, precisaremos da dependênciadiana-document:


    org.jnosql.diana
    diana-document
    0.0.5

Da mesma forma, devemos usar o módulodiana-key-value se o banco de dados NoSQL de trabalho for orientado a valores-chave:


    org.jnosql.diana
    diana-key-value
    0.0.5

E, finalmente, o módulodiana-column se for orientado a colunas:


    org.jnosql.diana
    diana-column
    0.0.5

As versões mais recentes podem ser encontradas emMaven Central.

2.2. Driver Diana Eclipse JNoSQL

The driver is a set of implementations of the API for the most common NoSQL databases.

Existe uma implementação por banco de dados NoSQL. If the database is multi-model, the driver should implement all supported APIs.

Por exemplo,couchbase-driver implementadiana-documentediana-key-value porqueCouchbase é orientado tanto para documento quanto para valor-chave.

Ao contrário dos bancos de dados relacionais, onde o driver normalmente é fornecido pelo fornecedor do banco de dados, aquithe driver is provided by Eclipse JNoSQL. Na maioria dos casos, esse driver é um invólucro da biblioteca oficial do fornecedor.

Para iniciar o driver, devemos incluir a API e a implementação correspondente para o banco de dados NoSQL escolhido.

Para o MongoDB, por exemplo, precisamos incluir as seguintes dependências:


    org.jnosql.diana
    diana-document
    0.0.5


    org.jnosql.diana
    mongodb-driver
    0.0.5

O processo por trás do trabalho com o Driver é simples.

Primeiro, precisamos de um beanConfiguration. Ao ler um arquivo de configuração do caminho de classe ou valores de codificação, oConfiguration é capaz de criar umFactory.. Em seguida, o usamos para criar umManager.

Finally, The Manager is responsible for pushing and retrieving the Entity to and from the NoSQL database.

Nas próximas subseções, explicaremos esse processo para cada tipo de banco de dados NoSQL.

2.3. Trabalhando com um Banco de Dados Orientado a Documentos

Neste exemplo,we’ll be using an embedded MongoDB, pois é simples de começar e não requer instalação. É orientado a documentos e as instruções a seguir são aplicáveis ​​a qualquer outro banco de dados NoSQL orientado a documentos.

No início, devemos fornecer todas as configurações necessárias para que o aplicativo interaja adequadamente com o banco de dados. Em sua forma mais elementar, devemos fornecerhosteport de um instância em execução do MongoDB.

Podemos fornecer essas configurações emmongodb-driver.properties localizado no caminho de classe:

#Define Host and Port
mongodb-server-host-1=localhost:27017

Ou como valores codificados:

Map map = new HashMap<>();
map.put("mongodb-server-host-1", "localhost:27017");

Em seguida, criamos o beanConfiguration para o tipo de documento:

DocumentConfiguration configuration = new MongoDBDocumentConfiguration();

A partir deste beanConfiguration, podemos criar umManagerFactory:

DocumentCollectionManagerFactory managerFactory = configuration.get();

Implicitamente, o métodoget() do beanConfiguration usa configurações do arquivo de propriedades. Também podemos obter esta fábrica a partir de valores codificados:

DocumentCollectionManagerFactory managerFactory
  = configuration.get(Settings.of(map));

OManagerFactory tem um método simplesget(), que leva o nome do banco de dados como parâmetro e cria oManager:

DocumentCollectionManager manager = managerFactory.get("my-db");

E finalmente, estamos prontos. OManager fornece todos os métodos necessários para interagir com o banco de dados NoSQL subjacente por meio doDocumentEntity.

Assim, poderíamos, por exemplo, inserir um documento:

DocumentEntity documentEntity = DocumentEntity.of("books");
documentEntity.add(Document.of("_id", "100"));
documentEntity.add(Document.of("name", "JNoSQL in Action"));
documentEntity.add(Document.of("pages", "620"));
DocumentEntity saved = manager.insert(documentEntity);

Também podemos procurar documentos:

DocumentQuery query = select().from("books").where("_id").eq(100).build();
List entities = manager.select(query);

E de maneira semelhante, poderíamos atualizar um documento existente:

saved.add(Document.of("author", "example"));
DocumentEntity updated = manager.update(saved);

E, finalmente, podemos excluir um documento armazenado:

DocumentDeleteQuery deleteQuery = delete().from("books").where("_id").eq("100").build();
manager.delete(deleteQuery);

Para executar a amostra, precisamos apenas acessar o módulojnosql-diana e executar o aplicativoDocumentApp.

Devemos ver a saída no console:

DefaultDocumentEntity{documents={pages=620, name=JNoSQL in Action, _id=100}, name='books'}
DefaultDocumentEntity{documents={pages=620, author=example, name=JNoSQL in Action, _id=100}, name='books'}
[]

2.4. Trabalhando com um Banco de Dados Orientado a Colunas

Para o propósito desta seção,we’ll use an embedded version of the Cassandra database, portanto, nenhuma instalação é necessária.

O processo para trabalhar com um banco de dados orientado a colunas é muito semelhante. Primeiro, adicionamos o driver Cassandra e a API da coluna ao pom:


    org.jnosql.diana
    diana-column
    0.0.5


    org.jnosql.diana
    cassandra-driver
    0.0.5

Em seguida, precisamos das definições de configuração especificadas no arquivo de configuração,diana-cassandra.properties, on o classpath. Como alternativa, também poderíamos usar valores de configuração codificados.

Então, com uma abordagem semelhante, criaremos umColumnFamilyManagere começaremos a manipular oColumnEntity:

ColumnConfiguration configuration = new CassandraConfiguration();
ColumnFamilyManagerFactory managerFactory = configuration.get();
ColumnFamilyManager entityManager = managerFactory.get("my-keySpace");

Portanto, para criar uma nova entidade, vamos invocar o métodoinsert():

ColumnEntity columnEntity = ColumnEntity.of("books");
Column key = Columns.of("id", 10L);
Column name = Columns.of("name", "JNoSQL in Action");
columnEntity.add(key);
columnEntity.add(name);
ColumnEntity saved = entityManager.insert(columnEntity);

Para executar a amostra e ver a saída no console, execute o aplicativoColumnFamilyApp.

2.5. Trabalhando com um Banco de Dados Orientado a Valores-chave

Nesta seção, usaremos o Hazelcast. Hazelcast is a key-value oriented NoSQL database. Para obter mais informações sobre o banco de dados Hazelcast, você pode verificar estelink.

O processo para trabalhar com o tipo orientado a valor-chave também é semelhante. Começamos adicionando essas dependências ao pom:


    org.jnosql.diana
    diana-key-value
    0.0.5


    org.jnosql.diana
    hazelcast-driver
    0.0.5

Então precisamos fornecer as definições de configuração. Em seguida, podemos obter umBucketManager e, em seguida, manipular oKeyValueEntity:

KeyValueConfiguration configuration = new HazelcastKeyValueConfiguration();
BucketManagerFactory managerFactory = configuration.get();
BucketManager entityManager = managerFactory.getBucketManager("books");

Digamos que queremos salvar o seguinte modeloBook:

public class Book implements Serializable {

    private String isbn;
    private String name;
    private String author;
    private int pages;

    // standard constructor
    // standard getters and setters
}

Portanto, criamos uma instânciaBook e a salvamos invocando o métodoput();

Book book = new Book(
  "12345", "JNoSQL in Action",
  "example", 420);
KeyValueEntity keyValueEntity = KeyValueEntity.of(
  book.getIsbn(), book);
entityManager.put(keyValueEntity);

Em seguida, para recuperar a instânciaBook salva:

Optional optionalValue = manager.get("12345");
Value value = optionalValue.get(); // or any other adequate Optional handling
Book savedBook = value.get(Book.class);

Para executar a amostra e ver a saída no console, execute o aplicativoKeyValueApp.

3. Camada de mapeamento Eclipse JNoSQL

The mapping layer, Artemis API, is a set of APIs that help map java annotated Objects to NoSQL databases. É baseado na API Diana e CDI (Context and Dependency Injection).

We can consider this API as JPA or ORM like for the NoSQL world. Essa camada também fornece uma API para cada tipo NoSQL e uma API principal para recursos comuns.

Nesta seção, vamos trabalhar com o banco de dados orientado a documentos MongoDB.

3.1. Dependências necessárias

Para habilitar o Artemis no aplicativo, precisamos adicionar a dependênciaartemis-configuration. Como o MongoDB é orientado a documentos, a dependênciaartemis-document também é necessária.

Para outros tipos de bancos de dados NoSQL, usaríamosartemis-column, artemis-key-valueeartemis-graph.

O driver Diana do MongoDB também é necessário:


    org.jnosql.artemis
    artemis-configuration
    0.0.5


    org.jnosql.artemis
    artemis-document
    0.0.5


    org.jnosql.diana
    mongodb-driver
    0.0.5

Artemis é baseado no CDI, portanto, também precisamos fornecer essa dependência do Maven:


    javax
    javaee-web-api
    8.0
    provided

3.2. O arquivo de configuração do documento

Uma configuração é um conjunto de propriedades para um determinado banco de dados que nos permite fornecer configurações fora do código. Por padrão, precisamos fornecer o arquivojnosql.json no recurso META-INF.

Este é um exemplo do arquivo de configuração:

[
    {
        "description": "The mongodb document configuration",
        "name": "document",
        "provider": "org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration",
        "settings": {
            "mongodb-server-host-1":"localhost:27019"
        }
    }
]

Precisamos especificar o nome da configuração acima definindo o atributoname em nossoConfigurationUnit.. Se a configuração estiver em um arquivo diferente, ele pode ser especificado usando o atributofileName.

Dada essa configuração, criamos uma fábrica:

@Inject
@ConfigurationUnit(name = "document")
private DocumentCollectionManagerFactory managerFactory;

E a partir dessa fábrica, podemos criar umDocumentCollectionManager:

@Produces
public MongoDBDocumentCollectionManager getEntityManager() {
    return managerFactory.get("todos");
}

ODocumentCollectionManager é um bean habilitado para CDI e é usado emTemplateeRepository.

3.3. Mapeamento

O mapeamento é um processo orientado por anotações pelo qual o modeloEntity é convertido para DianaEntityValue.

Vamos começar definindo um modeloTodo:

@Entity
public class Todo implements Serializable {

    @Id("id")
    public long id;

    @Column
    public String name;

    @Column
    public String description;

    // standard constructor
    // standard getters and setters
}

Conforme mostrado acima, temos as anotações básicas de mapeamento:@Entity, @Id,e@Column.

Agora, para manipular este modelo, precisamos de uma classeTemplate ou de uma interfaceRepository.

3.4. Trabalhando com o modelo

The template is thebridge between the entity model and the Diana API. Para um banco de dados orientado a documentos, começamos injetando o beanDocumentTemplate:

@Inject
DocumentTemplate documentTemplate;

E então, podemos manipular a EntidadeTodo. Por exemplo, podemos criar umTodo:

public Todo add(Todo todo) {
    return documentTemplate.insert(todo);
}

Ou podemos recuperar umTodo porid:

public Todo get(String id) {
    Optional todo = documentTemplate
      .find(Todo.class, id);
    return todo.get(); // or any other proper Optional handling
}

Para selecionar todas as entidades, construímos umDocumentQuerye invocamos o métodoselect():

public List getAll() {
    DocumentQuery query = select().from("Todo").build();
    return documentTemplate.select(query);
}

E, finalmente, podemos excluir uma entidadeTodo porid:

public void delete(String id) {
    documentTemplate.delete(Todo.class, id);
}

3.5. Trabalhando com o Repositório

Além da classeTemplate, também podemos gerenciar entidades por meio de informações dethe Repository interface which has methods for creating, updating, deleting and retrieving.

Para usar a interfaceRepository, fornecemos apenas uma subinterface doRepository:

public interface TodoRepository extends Repository {
    List findByName(String name);
    List findAll();
}

Pelo método a seguir e convenções de nomenclatura de parâmetros, uma implementação dessa interface é fornecida no tempo de execução como um bean CDI.

Neste exemplo, todas as entidadesTodo com umname correspondente são recuperadas pelo métodofindByName().

Agora podemos usá-lo:

@Inject
TodoRepository todoRepository;

O qualificadorDatabase nos permite trabalhar com mais de um banco de dados NoSQL no mesmo aplicativo. Ele vem com dois atributos, o tipo e o provedor.

Se o banco de dados é multi-modelo, precisamos especificar com qual modelo estamos trabalhando:

@Inject
@Database(value = DatabaseType.DOCUMENT)
TodoRepository todoRepository;

Além disso, se tivermos mais de um banco de dados do mesmo modelo, precisaremos especificar o provedor:

@Inject
@Database(value = DatabaseType.DOCUMENT, provider="org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration")
TodoRepository todoRepository;

Para executar a amostra, basta acessar o módulo jnosql-artemis e chamar este comando:

mvn package liberty:run

Este comando constrói, implanta e inicia o servidorOpen Liberty graças aoliberty-maven-plugin.

3.6. Testando o aplicativo

Como o aplicativo expõe um terminal REST, podemos usar qualquer cliente REST para nossos testes. Aqui usamos a ferramenta de curvatura.

Então, para salvar uma classe Todo:

curl -d '{"id":"120", "name":"task120", "description":"Description 120"}' -H "Content-Type: application/json" -X POST http://localhost:9080/jnosql-artemis/todos

e para obter todo o Todo:

curl -H "Accept: application/json" -X GET http://localhost:9080/jnosql-artemis/todos

Ou para obter apenas um Todo:

curl -H "Accept: application/json" -X GET http://localhost:9080/jnosql-artemis/todos/120

4. Conclusão

Neste tutorial, exploramos como o JNoSQL é capaz de abstrair a interação com um banco de dados NoSQL.

First, we have used JNoSQL Diana API to interact with the database with low-level code. Then, we used the JNoSQL Artemis API to work with friendly Java annotated Models.

Como de costume, podemos encontrar o código usado neste artigoover on Github.