Gestire strutture di database diverse spesso introduce una complessità significativa nell’architettura di sistema, specialmente quando sono richieste più istanze di database. Questa frammentazione può complicare le operazioni, aumentare i costi e ridurre l’efficienza. I database multimodello come ArangoDB forniscono una soluzione unificata per affrontare queste sfide. Semplificano l’architettura e ottimizzano la gestione dei dati supportando più modelli di dati — chiave-valore, documento e grafo — all’interno di un’unica istanza di database.
Rispetto ai database relazionali, i database NoSQL non aderiscono a uno standard universale come SQL. Invece, sono classificati in base alla loro struttura di archiviazione. Tra i tipi più popolari ci sono:
- Chiave-valore: Assomiglia a una
Map
di Java o a un dizionario di Python, questa struttura recupera valori interi come BLOB utilizzando una chiave. - Colonna ampia: Simile a chiave-valore ma suddivide i valori in colonne, offrendo un recupero dei dati più granulare.
- Documento: Strutturato come JSON o XML, questo tipo offre maggiore flessibilità nelle query.
- Grafo: Consente la modellazione e la query di relazioni complesse rappresentando entità e le loro connessioni.
Un database multimodello combina queste capacità in un unico sistema. Ad esempio, ArangoDB supporta modelli chiave-valore, documento e grafo, eliminando la necessità di database separati.
Questo articolo dimostra come utilizzare ArangoDB per esplorare modelli chiave-valore e documento nelle applicazioni Java utilizzando Jakarta NoSQL.
Configurazione di ArangoDB
Per iniziare con ArangoDB, Docker fornisce un modo diretto per gestire servizi di terze parti. Eseguendo il comando seguente, è possibile configurare un’istanza di ArangoDB con facilità:
docker run -e ARANGO_NO_AUTH=1 -d --name arangodb-instance -p 8529:8529 arangodb/arangodb
Esplorazione dei Dati Chiave-Valore
I database chiave-valore sono ideali per modelli di dati semplici. Creiamo un’applicazione di esempio per gestire dati sugli aeroporti utilizzando le capacità chiave-valore di ArangoDB. L’entità Airport
includerà due campi: code
(ID) e name
.
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 l’entità definita, è possibile utilizzare KeyValueTemplate
per interagire con il database. In questo tutorial, esploreremo ulteriormente le capacità di Jakarta NoSQL oltre alle annotazioni utilizzando Eclipse JNoSQL; è possibile creare il repository una volta che Eclipse JNoSQL implementa e supporta 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));
}
}
}
Questo programma genera un record casuale di aeroporto, lo inserisce nel database e lo recupera. Se stai eseguendo in locale, puoi controllare i valori nel database utilizzando il tuo browser con l’URL:
http://localhost:8529/_db/airport/_admin/aardvark/index.html#collections
Lavorare con i Dati Documento
Jakarta NoSQL offre ricche funzionalità per lavorare con database documentali, inclusi supporto per l’ereditarietà e la modellazione dei dati gerarchici. Sebbene i database NoSQL generalmente non supportino intrinsecamente queste funzionalità, Jakarta NoSQL colma questa lacuna con la sua API. Utilizziamo Jakarta NoSQL con ArangoDB per gestire i dati dei fornitori di cloud, incluse due specializzazioni: Amazon Web Services (AWS) e Azure.
Jakarta NoSQL utilizza le annotazioni @DiscriminatorColumn
, @DiscriminatorValue
e @Inheritance
per gestire l’ereditarietà nei database documentali.
- L’annotazione
@DiscriminatorColumn
specifica il campo utilizzato per identificare un tipo di entità nel documento del database. - L’annotazione
@DiscriminatorValue
definisce il valore specifico per ciascuna sottoclasse, garantendo che siano correttamente identificate. - L’annotazione
@Inheritance
indica che la gerarchia di classi sarà mappata nel database.
Per prima cosa, definiamo la classe base per i fornitori di cloud:
"type") (
public class CloudProvider {
protected String id;
protected String region;
}
Successivamente, introduciamo le classi specializzate dei fornitori di cloud. Questi esempi mostrano come Jakarta NoSQL sfrutti le annotazioni @DiscriminatorValue
per distinguere tra diversi tipi di documenti. Ogni specializzazione — AWS e Azure — eredita dalla classe base CloudProvider
, definendo anche attributi unici per ciascun fornitore. Inoltre, sono forniti metodi factory (of
) per generare dati di esempio a scopo dimostrativo.
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;
}
}
Infine, vediamo come utilizzare il DocumentTemplate
per interagire con il database. Questo codice dimostra la creazione di istanze dei provider AWS e Azure, l’inserimento nel database e il recupero. L’implementazione sfrutta l’API di Jakarta NoSQL per gestire la persistenza dei dati, garantendo che la logica dell’ereditarietà e del discriminatore venga applicata in modo trasparente durante l’archiviazione e il recupero.
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() {
}
}
Conclusione
Le capacità multimodello di ArangoDB lo rendono una scelta versatile per le applicazioni moderne. Combinare modelli chiave-valore e documenti in un singolo database semplifica l’architettura dei dati pur conservando flessibilità. Con Jakarta NoSQL, l’integrazione di ArangoDB nelle applicazioni Java diventa senza soluzione di continuità, sfruttando annotazioni e paradigmi di programmazione familiari.
Per il codice completo, visita il Repository GitHub.
Source:
https://dzone.com/articles/arangodb-success-through-multivalue-database