Ein Handbuch zu Eclipse JNoSQL

1. Überblick

Eclipse JNoSQL ist eine Reihe von APIs und Implementierungen, die die Interaktion von Java-Anwendungen mit NoSQL-Datenbanken vereinfachen.

In diesem Artikel erfahren Sie, wie Sie JNoSQL für die Interaktion mit einer NoSQL-Datenbank einrichten und konfigurieren. Wir arbeiten sowohl mit der Kommunikations- als auch mit der Zuordnungsebene.

2. Eclipse JNoSQL-Kommunikationsschicht

Technisch gesehen besteht die Kommunikationsschicht aus zwei Modulen:

  • Diana API und ein Treiber. **

  • Während die API eine Abstraktion zu NoSQL-Datenbanktypen definiert, bietet der Treiber Implementierungen für die meisten bekannten Datenbanken ** .

Wir können dies mit dem JDBC-API- und JDBC-Treiber in relationalen Datenbanken vergleichen.

2.1. Eclipse JNoSQL Diana API

Einfach ausgedrückt, gibt es vier grundlegende Typen von NoSQL-Datenbanken: Schlüsselwert, Spalte, Dokument und Diagramm.

Die Diana API von Eclipse JNoSQL definiert drei Module:

  1. diana-key-value

  2. Diana-Säule

  3. Diana-Dokument

Der NoSQL-Diagrammtyp wird von der API nicht abgedeckt, da er bereits von Apache ThinkerPop abgedeckt wird.

Die API basiert auf einem Kernmodul, diana-core, und definiert eine Abstraktion zu gängigen Konzepten wie Konfiguration, Factory, Manager, Entity und Value.

Um mit der API arbeiten zu können, müssen wir die Abhängigkeit des entsprechenden Moduls von unserem NoSQL-Datenbanktyp angeben.

Für eine dokumentorientierte Datenbank benötigen wir also die Abhängigkeit von diana-document :

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-document</artifactId>
    <version>0.0.5</version>
</dependency>

In ähnlicher Weise sollten wir das diana-key-value -Modul verwenden, wenn die NoSQL-Datenbank schlüsselwertorientiert ist:

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-key-value</artifactId>
    <version>0.0.5</version>
</dependency>

Und schließlich das diana-column -Modul, wenn es spaltenorientiert ist:

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-column</artifactId>
    <version>0.0.5</version>
</dependency>

Die neuesten Versionen finden Sie unter https://search.maven.org/classic/#search%7Cga%7C1%7Corg.jnosql.diana [Maven Central.

2.2. Eclipse JNoSQL Diana Treiber

  • Der Treiber besteht aus einer Reihe von Implementierungen der API für die gebräuchlichsten NoSQL-Datenbanken ** .

Es gibt eine Implementierung pro NoSQL-Datenbank. Bei einer Datenbank mit mehreren Modellen muss der Treiber alle unterstützten APIs implementieren .

Beispielsweise implementiert der couchbase-driver sowohl diana-document als auch diana-key-value , da Couchbase sowohl dokument- als auch schlüsselwertorientiert ist.

Im Gegensatz zu relationalen Datenbanken, bei denen der Treiber normalerweise vom Datenbankanbieter bereitgestellt wird, wird hier der Treiber von Eclipse JNoSQL bereitgestellt.

In den meisten Fällen handelt es sich bei diesem Treiber um einen Wrapper um die offizielle Herstellerbibliothek.

Um mit dem Treiber zu beginnen, sollten Sie die API und die entsprechende Implementierung für die ausgewählte NoSQL-Datenbank hinzufügen.

Für MongoDB müssen wir beispielsweise die folgenden Abhängigkeiten hinzufügen:

<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>diana-document</artifactId>
    <version>0.0.5</version>
</dependency>
<dependency>
    <groupId>org.jnosql.diana</groupId>
    <artifactId>mongodb-driver</artifactId>
    <version>0.0.5</version>
</dependency>

Die Arbeit mit dem Treiber ist einfach.

Zunächst benötigen wir eine Configuration -Bean. Durch das Lesen einer Konfigurationsdatei aus den Klassenpfad- oder Hardcoding-Werten kann die Configuration eine Factory erstellen.

  • Der Manager ist schließlich dafür verantwortlich, die Entity in die NoSQL-Datenbank zu verschieben und von dieser abzurufen ** .

In den nächsten Unterabschnitten erklären wir diesen Prozess für jeden NoSQL-Datenbanktyp.

2.3. Arbeiten mit einer dokumentenorientierten Datenbank

In diesem Beispiel verwenden wir eine eingebettete MongoDB , da die Installation einfach ist und keine Installation erforderlich ist. Es ist dokumentenorientiert und die folgenden Anweisungen gelten für jede andere dokumentenorientierte NoSQL-Datenbank.

Ganz am Anfang sollten wir alle notwendigen Einstellungen vornehmen, damit die Anwendung ordnungsgemäß mit der Datenbank interagieren kann _. In ihrer elementarsten Form sollten wir den host und den port_ einer laufenden Instanz von MongoDB angeben.

Wir können diese Einstellungen entweder in mongodb-driver.properties im Klassenpfad angeben:

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

Oder als hart codierte Werte:

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

Als Nächstes erstellen wir die Configuration -Bean für den Dokumenttyp:

DocumentConfiguration configuration = new MongoDBDocumentConfiguration();

Aus dieser Configuration Bean können wir eine ManagerFactory erstellen:

DocumentCollectionManagerFactory managerFactory = configuration.get();

Die Methode get () der Configuration -Bean verwendet implizit Einstellungen aus der Eigenschaftendatei. Wir können diese Factory auch aus hartcodierten Werten erhalten:

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

Die ManagerFactory hat eine einfache Methode get (), , die den Datenbanknamen als Parameter übernimmt und die Manager erstellt:

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

Und zum Schluss sind wir bereit. Der _Manager stellt alle erforderlichen Methoden bereit, um mit der zugrunde liegenden NoSQL-Datenbank über die DocumentEntity._ zu interagieren.

So könnten wir beispielsweise ein Dokument einfügen:

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);

Wir könnten auch nach Dokumenten suchen:

DocumentQuery query = select().from("books").where("__id").eq(100).build();
List<DocumentEntity> entities = manager.select(query);

In ähnlicher Weise könnten wir ein vorhandenes Dokument aktualisieren:

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

Und schließlich können wir ein gespeichertes Dokument löschen:

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

Um das Beispiel auszuführen, müssen wir lediglich auf das Modul jnosql-diana zugreifen und die Anwendung DocumentApp ausführen.

Wir sollten die Ausgabe in der Konsole sehen:

DefaultDocumentEntity{documents={pages=620, name=JNoSQL in Action, __id=100}, name='books'}
DefaultDocumentEntity{documents={pages=620, author=baeldung, name=JNoSQL in Action, __id=100}, name='books'}[]----

[[working-with-entity]]

====  **  2.4. Arbeiten mit einer spaltenorientierten Datenbank **

Für die Zwecke dieses Abschnitts verwenden wir eine eingebettete Version der Cassandra-Datenbank, so dass keine Installation erforderlich ist.

Das Arbeiten mit einer spaltenorientierten Datenbank ist sehr ähnlich.

Als Erstes fügen wir dem Pom den Cassandra-Treiber und die Spalten-API hinzu:

[source,xml,gutter:,true]

<dependency> <groupId>org.jnosql.diana</groupId> <artifactId>diana-column</artifactId> <version>0.0.5</version> </dependency> <dependency> <groupId>org.jnosql.diana</groupId> <artifactId>cassandra-driver</artifactId> <version>0.0.5</version> </dependency>

Als nächstes benötigen wir die Konfigurationseinstellungen, die in der Konfigurationsdatei ____diana-cassandra.properties angegeben sind, ____auf dem Klassenpfad. Alternativ können auch fest codierte Konfigurationswerte verwendet werden.

Mit einem ähnlichen Ansatz erstellen wir einen __ColumnFamilyManager__ und beginnen mit der Bearbeitung der __ColumnEntity:

[source,java,gutter:,true]

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

Um eine neue Entität zu erstellen, rufen wir die Methode __insert () __ auf:

[source,java,gutter:,true]

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);

Führen Sie die Anwendung __ColumnFamilyApp__ aus, um das Beispiel auszuführen und die Ausgabe in der Konsole anzuzeigen.

[[working-with-entity]]

====  **  2.5. Arbeiten mit einer auf Schlüsselwerte ausgerichteten Datenbank **

In diesem Abschnitt verwenden wir den Hazelcast. **  Hazelcast ist eine auf Schlüsselwerte ausgerichtete NoSQL-Datenbank ** . Weitere Informationen zur Hazelcast-Datenbank finden Sie unter https://www.baeldung.com/java-hazelcast[link].

Das Verfahren zum Arbeiten mit dem Schlüsselwertorientierten Typ ist ebenfalls ähnlich. Wir beginnen damit, diese Abhängigkeiten zum pom hinzuzufügen:

[source,xml,gutter:,true]

<dependency> <groupId>org.jnosql.diana</groupId> <artifactId>diana-key-value</artifactId> <version>0.0.5</version> </dependency> <dependency> <groupId>org.jnosql.diana</groupId> <artifactId>hazelcast-driver</artifactId> <version>0.0.5</version> </dependency>

Dann müssen wir die Konfigurationseinstellungen angeben. Als Nächstes können wir einen __BucketManager__ erhalten und dann die __KeyValueEntity bearbeiten: __

[source,java,gutter:,true]

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

Angenommen, wir möchten das folgende __Book__-Modell speichern:

[source,java,gutter:,true]

public class Book implements Serializable {

private String isbn;
private String name;
private String author;
private int pages;
   //standard constructor
   //standard getters and setters
}
Also erstellen wir eine __Book__-Instanz und speichern sie dann durch Aufrufen der __put () __-Methode.

[source,java,gutter:,true]

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

Dann rufen Sie die gespeicherte __Book__-Instanz ab:

[source,java,gutter:,true]

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

Führen Sie die Anwendung __KeyValueApp__ aus, um das Beispiel auszuführen und die Ausgabe in der Konsole anzuzeigen.

[[mapping-layer]]

===  **  3. Eclipse JNoSQL-Zuordnungsebene **

**  Die Mapping-Ebene, Artemis API, besteht aus einer Reihe von APIs, mit denen mit Java kommentierte Objekte NoSQL-Datenbanken zugeordnet werden können ** . Es basiert auf der Diana API und CDI (Context and Dependency Injection).

**  Wir können diese API als JPA oder ORM wie für die NoSQL-Welt betrachten ** . Diese Schicht bietet auch eine API für jeden NoSQL-Typ und eine Core-API für allgemeine Funktionen.

In diesem Abschnitt arbeiten wir mit der dokumentenorientierten Datenbank von MongoDB.

[[dependencies]]

====  **  3.1. Erforderliche Abhängigkeiten **

Um Artemis in der Anwendung zu aktivieren, müssen Sie die Abhängigkeit __https://search.maven.org/classic/#search%7Cga%7C1%7Cartemis-configuration[artemis-configuration]__ hinzufügen.

Da MongoDB dokumentorientiert ist, ist auch die Abhängigkeit https://search.maven.org/classic/#search%7Cga%7C1%7Cartemis-document[artemis-document]erforderlich.

Für andere Arten von NoSQL-Datenbanken würden wir __artemis-column, artemis-key-value__ und __artemis-graph__ verwenden.

Der Diana-Treiber für MongoDB wird ebenfalls benötigt:

[source,xml,gutter:,true]

<dependency> <groupId>org.jnosql.artemis</groupId> <artifactId>artemis-configuration</artifactId> <version>0.0.5</version> </dependency> <dependency> <groupId>org.jnosql.artemis</groupId> <artifactId>artemis-document</artifactId> <version>0.0.5</version> </dependency> <dependency> <groupId>org.jnosql.diana</groupId> <artifactId>mongodb-driver</artifactId> <version>0.0.5</version> </dependency>

Artemis basiert auf CDI, daher müssen wir auch diese Maven-Abhängigkeit angeben:

[source,xml,gutter:,true]

<dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency>

[[config-file]]

====  **  3.2. Die Dokumentkonfigurationsdatei **

Eine Konfiguration ist eine Gruppe von Eigenschaften für eine bestimmte Datenbank, mit der Einstellungen außerhalb des Codes vorgenommen werden können. Standardmäßig müssen wir die Datei __jnosql.json__ unter der Ressource META-INF bereitstellen.

Dies ist ein Beispiel für die Konfigurationsdatei:

[source,javascript,gutter:,true]

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

Der Konfigurationsname muss oben angegeben werden, indem das __name__-Attribut in unserer __ConfigurationUnit__ gesetzt wird. Wenn sich die Konfiguration in einer anderen Datei befindet, kann sie mit dem __fileName__-Attribut angegeben werden.

Bei dieser Konfiguration erstellen wir eine Fabrik:

[source,java,gutter:,true]

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

Und aus dieser Factory können wir einen __DocumentCollectionManager__ erstellen:

[source,java,gutter:,true]

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

Die __DocumentCollectionManager__ ist eine CDI-aktivierte Bean und wird sowohl in der __Template__ als auch im __Repository verwendet.

====  **  3.3. Kartierung**

Das Mapping ist ein annotationsgesteuerter Prozess, durch den das __Entity__-Modell in den Diana __EntityValue-Wert konvertiert wird.

Beginnen wir mit der Definition eines __Todo__-Modells:

[source,java,gutter:,true]

@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
}
Wie oben gezeigt, haben wir die grundlegenden Annotationen für das Mapping: __ @ Entity, @ Id, __ und __@Column.__

Um dieses Modell zu bearbeiten, benötigen wir entweder eine __Template__-Klasse oder eine __Repository__-Schnittstelle.

====  **  3.4. Mit der Vorlage arbeiten **

**  Die Vorlage ist die **  **  Brücke zwischen dem Entitätsmodell und der Diana API ** . Für eine dokumentenorientierte Datenbank fügen wir zunächst die __DocumentTemplate__-Bean ein:

[source,java,gutter:,true]

@Inject DocumentTemplate documentTemplate;

Und dann können wir die __Todo__-Entität manipulieren. Zum Beispiel können wir ein __Todo__ erstellen:

[source,java,gutter:,true]

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

Oder wir können einen __Todo__ von __id__ abrufen:

[source,java,gutter:,true]

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

Um alle Entitäten auszuwählen, erstellen wir eine __DocumentQuery__ und rufen dann die __select () __ -Methode auf:

[source,java,gutter:,true]

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

Und schließlich können wir eine __Todo__-Entität mit __id__ löschen:

[source,java,gutter:,true]

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

====  **  3.5. Arbeiten mit dem Repository **

Zusätzlich zur __Template__-Klasse können wir Entitäten auch über die __Repository__-Schnittstelle verwalten, die Methoden zum Erstellen, Aktualisieren, Löschen und Abrufen von **  Informationen enthält.

Um die __Repository__-Schnittstelle zu verwenden, stellen wir nur eine Subschnittstelle des __Repository bereit: __

[source,java,gutter:,true]

public interface TodoRepository extends Repository<Todo, String> { List<Todo> findByName(String name); List<Todo> findAll(); }

Mit den folgenden Methoden- und Parameternamenkonventionen wird eine Implementierung dieser Schnittstelle zur Laufzeit als CDI-Bean bereitgestellt.

In diesem Beispiel werden alle __Todo__-Entitäten mit einem übereinstimmenden __name__ von der __findByName () __-Methode abgerufen.

Wir können es jetzt verwenden:

[source,java,gutter:,true]

@Inject TodoRepository todoRepository;

Mit dem __Database__-Qualifikationsmerkmal können wir mit mehr als einer NoSQL-Datenbank in derselben Anwendung arbeiten. Es gibt zwei Attribute, den Typ und den Anbieter.

Wenn die Datenbank aus mehreren Modellen besteht, müssen wir angeben, mit welchem ​​Modell wir arbeiten:

[source,java,gutter:,true]

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

Wenn wir mehr als eine Datenbank des gleichen Modells haben, müssen wir zusätzlich den Anbieter angeben:

[source,java,gutter:,true]

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

Um das Beispiel auszuführen, greifen Sie einfach auf das Modul jnosql-artemis zu und rufen Sie den folgenden Befehl auf:

[source,bash,gutter:,true]

mvn package liberty:run

Mit diesem Befehl wird der Server https://www.openliberty.io/[Open Liberty]mithilfe des https://github.com/WASdev/ci.maven#liberty-maven-plugin Plugin].

====  **  3.6. Anwendung testen **

Da die Anwendung einen REST-Endpunkt verfügbar macht, können wir jeden REST-Client für unsere Tests verwenden. Hier haben wir das Curl-Tool verwendet.

So speichern Sie eine Todo-Klasse:

[source,bash,gutter:,true]

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

und um alle Todo zu bekommen:

[source,bash,gutter:,true]

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

Oder um nur einen Todo zu bekommen:

[source,bash,gutter:,true]

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

===  **  4. Fazit**

In diesem Tutorial haben wir untersucht, wie JNoSQL die Interaktion mit einer NoSQL-Datenbank abstrahieren kann.

**  Erstens haben wir die JNoSQL-Diana-API verwendet, um mit Low-Level-Code mit der Datenbank zu interagieren. Anschließend haben wir die Artemis-API von JNoSQL verwendet, um mit benutzerfreundlichen Java-Modellen **  zu arbeiten.

Wie üblich finden Sie den in diesem Artikel verwendeten Code https://github.com/eugenp/tutorials/tree/master/persistence-modules/jnosql Über Github].