Lidar com estruturas de banco de dados diversas frequentemente introduz uma complexidade significativa na arquitetura do sistema, especialmente quando múltiplas instâncias de banco de dados são necessárias. Essa fragmentação pode complicar operações, aumentar custos e reduzir a eficiência. Bancos de dados multimodelo como o ArangoDB fornecem uma solução unificada para enfrentar esses desafios. Eles simplificam a arquitetura e otimizam a gestão de dados ao suportar múltiplos modelos de dados — chave-valor, documento e grafo — dentro de uma única instância de banco de dados.
Ao contrário dos bancos de dados relacionais, bancos de dados NoSQL não seguem um padrão universal como o SQL. Em vez disso, eles são categorizados com base em sua estrutura de armazenamento. Entre os tipos populares estão:
- Chave-valor: Semelhante a um
Map
em Java ou a um dicionário em Python, essa estrutura recupera valores inteiros como BLOBs usando uma chave. - Coluna-larga: Semelhante à chave-valor, mas divide os valores em colunas, oferecendo uma recuperação de dados mais granular.
- Documento: Estruturado como JSON ou XML, esse tipo fornece maior flexibilidade nas consultas.
- Grafo: Permite modelagem e consulta complexas de relacionamentos ao representar entidades e suas conexões.
Um banco de dados multimodelo combina essas capacidades em um único sistema. Por exemplo, o ArangoDB suporta modelos de chave-valor, documento e grafo, eliminando a necessidade de bancos de dados separados.
Este artigo demonstra como usar o ArangoDB para explorar modelos de chave-valor e documento em aplicações Java utilizando Jakarta NoSQL.
Configurando o ArangoDB
Para começar com o ArangoDB, o Docker oferece uma maneira simples de gerenciar serviços de terceiros. Ao executar o seguinte comando, você pode configurar uma instância do ArangoDB com facilidade:
docker run -e ARANGO_NO_AUTH=1 -d --name arangodb-instance -p 8529:8529 arangodb/arangodb
Explorando Dados de Chave-Valor
Bancos de dados de chave-valor são ideais para modelos de dados simples. Vamos criar um aplicativo de exemplo para gerenciar dados de aeroportos usando as capacidades de chave-valor do ArangoDB. A entidade Aeroporto
incluirá dois campos: código
(ID) e nome
.
import jakarta.nosql.Column;
import jakarta.nosql.Entity;
import jakarta.nosql.Id;
import net.datafaker.Faker;
import net.datafaker.providers.base.Aviation;
import java.util.Objects;
public class Airport {
private String code;
private String name;
public String getCode() {
return code;
}
public String getName() {
return name;
}
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
Airport airport = (Airport) o;
return Objects.equals(code, airport.code);
}
public int hashCode() {
return Objects.hashCode(code);
}
public String toString() {
return "Airport{" +
"code='" + code + '\'' +
", name='" + name + '\'' +
'}';
}
public static Airport of(Faker faker) {
Aviation aviation = faker.aviation();
var airport = new Airport();
airport.code = aviation.airport();
airport.name = aviation.airport();
return airport;
}
}
Com a entidade definida, você pode usá-la KeyValueTemplate
para interagir com o banco de dados. Neste tutorial, exploraremos mais da capacidade Jakarta NoSQL além das anotações usando Eclipse JNoSQL; você pode criar o repositório uma vez que o Eclipse JNoSQL implemente e suporte Jakarta Data.
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import net.datafaker.Faker;
import org.eclipse.jnosql.mapping.keyvalue.KeyValueTemplate;
public class App {
public static void main(String[] args) {
var faker = new Faker();
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
KeyValueTemplate template = container.select(KeyValueTemplate.class).get();
var airport = template.put(Airport.of(faker));
System.out.println(template.get(airport.getCode(), Airport.class));
}
}
}
Este programa gera um registro de aeroporto aleatório, insere-o no banco de dados e o recupera. Se você estiver executando localmente, pode verificar os valores no banco de dados usando seu navegador com a URL:
http://localhost:8529/_db/airport/_admin/aardvark/index.html#collections
Trabalhando com Dados de Documento
Jakarta NoSQL oferece recursos ricos para trabalhar com bancos de dados de documentos, incluindo suporte a herança e modelagem de dados hierárquicos. Embora os bancos de dados NoSQL geralmente não suportem esses recursos de forma inerente, o Jakarta NoSQL preenche essa lacuna com sua API. Vamos usar o Jakarta NoSQL com o ArangoDB para gerenciar dados de provedores de nuvem, incluindo duas especializações: Amazon Web Services (AWS) e Azure.
O Jakarta NoSQL utiliza as anotações @DiscriminatorColumn
, @DiscriminatorValue
e @Inheritance
para gerenciar a herança em bancos de dados de documentos.
- A anotação
@DiscriminatorColumn
especifica o campo usado para identificar um tipo de entidade no documento do banco de dados. - A anotação
@DiscriminatorValue
define o valor específico para cada subclasse, garantindo que elas sejam corretamente identificadas. - A anotação
@Inheritance
indica que a hierarquia de classes será mapeada no banco de dados.
Primeiro, defina a classe base para provedores de nuvem:
"type") (
public class CloudProvider {
protected String id;
protected String region;
}
Em seguida, apresentamos as classes especializadas de provedores de nuvem. Esses exemplos mostram como o Jakarta NoSQL utiliza anotações @DiscriminatorValue
para distinguir entre diferentes tipos de documentos. Cada especialização — AWS e Azure — herda da classe base CloudProvider
, enquanto também define atributos únicos para cada provedor. Além disso, métodos de fábrica (of
) são fornecidos para gerar dados de exemplo para fins de demonstração.
AWSCloudProvider
import jakarta.nosql.Column;
import jakarta.nosql.DiscriminatorValue;
import jakarta.nosql.Entity;
import net.datafaker.Faker;
import java.util.UUID;
"AWS") (
public class AWSCloudProvider extends CloudProvider {
private String accountId;
public String getAccountId() {
return accountId;
}
public String toString() {
return "AWSCloudProvider{" +
"accountId='" + accountId + '\'' +
", id='" + id + '\'' +
", region='" + region + '\'' +
'}';
}
public static AWSCloudProvider of(Faker faker) {
var aws = faker.aws();
var cloudProvider = new AWSCloudProvider();
cloudProvider.region = aws.region();
cloudProvider.region = aws.region();
cloudProvider.id = UUID.randomUUID().toString();
cloudProvider.accountId = aws.accountId();
return cloudProvider;
}
}
AzureCloudProvider
package org.soujava.demos.arangodb.document;
import jakarta.nosql.Column;
import jakarta.nosql.DiscriminatorValue;
import jakarta.nosql.Entity;
import net.datafaker.Faker;
import java.util.UUID;
"AZURE") (
public class AzureCloudProvider extends CloudProvider {
private String tenantId;
public String getTenantId() {
return tenantId;
}
public String toString() {
return "AzureCloudProvider{" +
"tenantId='" + tenantId + '\'' +
", id='" + id + '\'' +
", region='" + region + '\'' +
'}';
}
public static AzureCloudProvider of(Faker faker) {
var azure = faker.azure();
var cloudProvider = new AzureCloudProvider();
cloudProvider.region = azure.region();
cloudProvider.region = azure.region();
cloudProvider.id = UUID.randomUUID().toString();
cloudProvider.tenantId = azure.tenantId();
return cloudProvider;
}
}
Finalmente, vamos ver como usar o DocumentTemplate
para interagir com o banco de dados. Este código demonstra a criação de instâncias dos provedores AWS e Azure, inserindo-os no banco de dados e recuperando-os. A implementação utiliza a API do Jakarta NoSQL para lidar com a persistência de dados, garantindo que a lógica de herança e de discriminador sejam aplicadas de forma transparente durante o armazenamento e recuperação.
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import net.datafaker.Faker;
import org.eclipse.jnosql.mapping.document.DocumentTemplate;
import java.util.List;
import java.util.logging.Logger;
public class App {
private static final Logger LOGGER = Logger.getLogger(App.class.getName());
public static void main(String[] args) {
var faker = new Faker();
LOGGER.info("Starting the application");
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
var template = container.select(DocumentTemplate.class).get();
LOGGER.info("Creating 10 documents");
for (int index = 0; index < 5; index++) {
template.insert(List.of(AWSCloudProvider.of(faker), AzureCloudProvider.of(faker)));
}
System.out.println("The cloud providers here");
template.select(CloudProvider.class).stream().forEach(System.out::println);
System.out.println("The AWS cloud providers here");
template.select(AWSCloudProvider.class).stream().forEach(System.out::println);
System.out.println("The Azure cloud providers here");
template.select(AzureCloudProvider.class).stream().forEach(System.out::println);
}
}
private App() {
}
}
Conclusão
As capacidades multimodelo do ArangoDB o tornam uma escolha versátil para aplicações modernas. Combinar modelos chave-valor e de documentos em um único banco de dados simplifica a arquitetura de dados, mantendo a flexibilidade. Com o Jakarta NoSQL, a integração do ArangoDB em aplicações Java se torna perfeita, aproveitando anotações familiares e paradigmas de programação.
Para ver o código completo, visite o Repositório no GitHub.
Source:
https://dzone.com/articles/arangodb-success-through-multivalue-database