Manejar diversas estructuras de bases de datos a menudo introduce una complejidad significativa en la arquitectura del sistema, especialmente cuando se requieren múltiples instancias de bases de datos. Esta fragmentación puede complicar las operaciones, aumentar los costos y reducir la eficiencia. Las bases de datos multimodelo como ArangoDB proporcionan una solución unificada para abordar estos desafíos. Simplifican la arquitectura y optimizan la gestión de datos al soportar múltiples modelos de datos: clave-valor, documento y gráfico, dentro de una sola instancia de base de datos.
A diferencia de las bases de datos relacionales, las bases de datos NoSQL no se adhieren a un estándar universal como SQL. En cambio, se clasifican según su estructura de almacenamiento. Entre los tipos populares se encuentran:
- Clave-valor: Parecido a un
Map
de Java o un diccionario de Python, esta estructura recupera valores completos como BLOBs utilizando una clave. - Columna ancha: Similar a clave-valor, pero divide los valores en columnas, ofreciendo una recuperación de datos más granular.
- Documento: Estructurado como JSON o XML, este tipo proporciona mayor flexibilidad en las consultas.
- Gráfico: Permite modelar y consultar relaciones complejas representando entidades y sus conexiones.
Una base de datos multimodelo combina estas capacidades en un solo sistema. Por ejemplo, ArangoDB soporta modelos de clave-valor, documento y gráfico, eliminando la necesidad de bases de datos separadas.
Este artículo demuestra cómo usar ArangoDB para explorar modelos de clave-valor y documento en aplicaciones Java utilizando Jakarta NoSQL.
Configuración de ArangoDB
Para comenzar con ArangoDB, Docker proporciona una manera sencilla de gestionar servicios de terceros. Ejecutando el siguiente comando, puedes configurar una instancia de ArangoDB con facilidad:
docker run -e ARANGO_NO_AUTH=1 -d --name arangodb-instance -p 8529:8529 arangodb/arangodb
Explorando Datos Clave-Valor
Las bases de datos clave-valor son ideales para modelos de datos simples. Vamos a crear una aplicación de ejemplo para gestionar datos de aeropuertos utilizando las capacidades clave-valor de ArangoDB. La entidad Aeropuerto
incluirá dos campos: código
(ID) y nombre
.
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;
}
}
Con la entidad definida, puedes usar KeyValueTemplate
para interactuar con la base de datos. En este tutorial, exploraremos más de la capacidad NoSQL de Jakarta más allá de las anotaciones utilizando Eclipse JNoSQL; puedes crear el repositorio una vez que Eclipse JNoSQL implemente y soporte 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 genera un registro de aeropuerto aleatorio, lo inserta en la base de datos y lo recupera. Si estás ejecutando localmente, puedes verificar los valores en la base de datos usando tu navegador con la URL:
http://localhost:8529/_db/airport/_admin/aardvark/index.html#collections
Trabajando Con Datos de Documentos
Jakarta NoSQL proporciona funciones avanzadas para trabajar con bases de datos de documentos, incluido el soporte para herencia y modelado de datos jerárquicos. Si bien las bases de datos NoSQL generalmente no admiten inherentemente estas funciones, Jakarta NoSQL cubre esta brecha con su API. Utilicemos Jakarta NoSQL con ArangoDB para gestionar datos de proveedores en la nube, que incluyen dos especializaciones: Amazon Web Services (AWS) y Azure.
Jakarta NoSQL utiliza las anotaciones @DiscriminatorColumn
, @DiscriminatorValue
y @Inheritance
para gestionar la herencia en bases de datos de documentos.
- La anotación
@DiscriminatorColumn
especifica el campo utilizado para identificar un tipo de entidad en el documento de la base de datos. - La anotación
@DiscriminatorValue
define el valor específico para cada subclase, asegurando que sean identificadas correctamente. - La anotación
@Inheritance
indica que la jerarquía de clases se mapeará en la base de datos.
Primero, definimos la clase base para los proveedores en la nube:
"type") (
public class CloudProvider {
protected String id;
protected String region;
}
A continuación, presentamos las clases especializadas de proveedores en la nube. Estos ejemplos muestran cómo Jakarta NoSQL aprovecha las anotaciones @DiscriminatorValue
para distinguir entre diferentes tipos de documentos. Cada especialización — AWS y Azure — hereda de la clase base CloudProvider
, al mismo tiempo que define atributos únicos para cada proveedor. Además, se proporcionan métodos de fábrica (of
) para generar datos de muestra con fines de demostración.
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;
}
}
ProveedorNubeAzure
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, veamos cómo usar el DocumentTemplate
para interactuar con la base de datos. Este código demuestra la creación de instancias de proveedores de AWS y Azure, insertándolas en la base de datos y recuperándolas. La implementación aprovecha la API de Jakarta NoSQL para manejar la persistencia de datos, asegurando que la lógica de herencia y discriminación se aplique sin problemas durante el almacenamiento y la recuperación.
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() {
}
}
Conclusión
Las capacidades multimodelo de ArangoDB lo convierten en una opción versátil para aplicaciones modernas. Combinar modelos de clave-valor y de documentos en una sola base de datos simplifica tu arquitectura de datos mientras se mantiene la flexibilidad. Con Jakarta NoSQL, integrar ArangoDB en aplicaciones Java se vuelve sin problemas, aprovechando anotaciones y paradigmas de programación familiares.
Para el código completo, visita el Repositorio de GitHub.
Source:
https://dzone.com/articles/arangodb-success-through-multivalue-database