Jakarta Data und NoSQL – Standardisierte Datenzugriffe für Jakarta EE

Die Datenmenge, die Anwendungen heutzutage erfassen, wächst rasant. Viele Anwendungen müssen sowohl relationale SQL- als auch nicht-relationale NoSQL-Datenbanken unterstützen. Jakarta Data bietet eine API für einfachen Datenzugriff. Entwickler können den Persistenzmechanismus und das Modell mithilfe gemeinsamer Funktionen wie dem Repository-Muster trennen und nahtlos zwischen SQL- und NoSQL-Datenbanken wechseln oder sogar beide in derselben Anwendung verwenden.

Was sind NoSQL-Datenbanken?

NoSQL-Datenbanken, auch „Nicht Nur SQL“, „Nicht-Relational“ oder „Nicht-SQL“ genannt, sind eine Art Datenbankverwaltungssystem, bei dem die Speicherung und Abfrage von Daten anders erfolgt als bei herkömmlichen relationalen Datenbanken.

Anstelle der tabellarischen Struktur einer relationalen Datenbank mit Tabellen und Spalten verwenden NoSQL-Datenbanken häufig andere Datenstrukturen, beispielsweise ein JSON-Dokument oder eine Graphenstruktur. Da das nicht-relationale Datenbankdesign kein Schema erfordert, bietet es mehr Flexibilität und Skalierbarkeit bei der Verwaltung großer und meist unstrukturierter Daten.

NoSQL eignet sich auch gut für verteilte Datenbanken, bei denen Daten kopiert und auf mehreren Servern gespeichert werden, entweder lokal oder remote. Dies verbessert die Verfügbarkeit und Zuverlässigkeit der Daten. Sollten Daten nicht verfügbar sein, kann der Rest der Datenbank weiterlaufen. Die meisten relationalen Datenbanksysteme funktionieren jedoch nicht mehr, wenn beispielsweise die Liste der Schemata oder Tabellen fehlt oder beschädigt ist.

Funktionen von NoSQL-Datenbanken

Während relationale Datenbanken die Speicherung optimieren und Redundanz vermeiden, können NoSQL-Datenbanken große Mengen unstrukturierter oder halbstrukturierter Daten verarbeiten und bieten Skalierbarkeit und Flexibilität für moderne verteilte Anwendungen.

Die wichtigsten Funktionen von NoSQL-Datenbanken sind:

  • Flexible Datenstrukturen und dynamische Schemata statt fester Schemata
  • Horizontale Skalierbarkeit
  • Geringe Latenz
  • Große Anzahl gleichzeitiger Benutzer und Datenmengen
  • Verteilte Natur
  • Höhere Leistung und Geschwindigkeit

Arten von NoSQL-Datenbanken

Die wichtigsten Typen von NoSQL-Datenbanken sind:

  • Schlüssel-Wert -Speicher
  • Spaltenorientiert
  • Dokumenten-Speicher
  • Graphdatenbanken​
  • Zeitreihen​

Schlüssel-Wert-Speicher (Datenbanken) sind der einfachste Typ von NoSQL-Datenbanken. Daten werden in Schlüssel-Wert-Paaren gespeichert, im Wesentlichen wie eine Map in der Java Collections API.

Beispiele für Schlüssel-Wert-Speicher sind Amazon DynamoDB, S3, Redis, Hazelcast oder Memcached

Spaltenorientierte Datenbanken speichern Daten in Spalten statt in Zeilen, wie dies bei relationalen Datenbanken der Fall ist. Dieser Datenbanktyp eignet sich gut für die Kombination strukturierter , halbstrukturierter und unstrukturierter Daten und bietet hohe Parallelität und Skalierbarkeit.

Beispiele für spaltenorientierte Datenbanken sind Apache HBase, Apache Cassandra, Sxylla, Clouddata , SimpleDB oder Azure Cosmos DB.

Dokumentenorientierte NoSQL-Datenbanken speichern Daten in flexiblen Dokumenten, meist im JSON-, BSON- oder XML-Format, anstelle starrer Tabellen. Diese Dokumente können unterschiedliche Strukturen haben, was sich gut für Anwendungen mit Bedarf variabler Datendefinitionen eignet und schnellere, agile Entwicklungszyklen erlauben kann.

Beispiele für dokumentenorientierte NoSQL-Datenbanken sind MongoDB, CouchDB, Couchbase Server, ElasticSearch, Google Cloud Firestore, Amazon DocumentDB oder DynamoDB.

Graphdatenbanken ermöglichen die Speicherung komplexerer Beziehungen als relationale Datenbanken. Das Modell Graph wendet die Graphentheorie an , Daten werden als Netzwerk aus Knoten und Kanten gespeichert. Graphdatenbanken eignen sich gut für den „Social Graph“ in sozialen Netzwerken, aber auch für KI-Modelle, insbesondere Retrieval Augmented Generation (RAG)-Datenbanken.

Beispiele für Graphdatenbanken sind Neo4J, ArangoDB , OrientDb , InfoGrid , Sones, HyperGraphDB oder JanusGraph .

Eine Zeitreihendatenbank kann als eine spezielle Form eines Schlüssel-Wert-Speichers betrachtet werden, mit einem Zeitstempel als Schlüssel und mit dem Zeitstempel verknüpften Werten.

Beispiele für Zeitreihendatenbanken sind InfluxDB , KairosDB , TimescaleDB , Apache Pinot, Riak-TS oder Prometheus.

Einige NoSQL-Datenbanken kombinieren mehr als einen Typ, zum Beispiel:

  1. OrientDB (Graph, Dokument )
  2. Couchbase (Schlüssel- Wert , Dokument )
  3. ArangoDB (Dokument, Graph, Schlüssel-Wert)
  4. Elasticsearch ( Dokument , Diagramm)

SQL vs. NoSQL

BesonderheitSQLNoSQL
SchemaBehobenDynamisch oder keiner
SÄURE/BASESÄUREBASE oder begrenzt SÄURE
DatenmodellStrukturiert, tabellenbasiertFlexibel: Dokumente, Schlüssel-Wert, Diagramme
Datenstruktur​NormalisiertDenormalisiert
SkalierbarkeitVertikal SkalierungHorizontale Skalierung
Beste AnwendungsfälleTransaktional , flussbasierte AnwendungenBig Data, KI, Echtzeit-Datenanalyse, Embedded/IoT
Unterschiede zwischen SQL und NoSQL

ACID vs. BASE-Prinzipien:

ACID                                                                                  BASE

ACID vs. BASE
• Atomarität
• Konsistenz
• Isolierung
• Haltbarkeit  
• Grundsätzlich Verfügbar
• Weicher Zustand
• Eventuelle Konsistenz  

Hier sind die am häufigsten von verschiedenen Datenbanktypen verwendeten Schlüsselwörter:

SQLSchlüsselwertSpalteDokumentierenGraph
TischEimerSpalte FamilieSammlung
ReiheSpalteDokumentierenScheitel
SpalteSchlüssel- / WertpaarSchlüssel- / WertpaarScheitelpunkt- und Kanteneigenschaft
BeziehungLinkRand
Index
Von verschiedenen Datenbanktypen verwendete Schlüsselwörter

Die Verwendung von JPA für NoSQL-Datenbanken kann problematisch sein:

  1. Asynchron Speichert
  2. Aysnc -Rückruf
  3. Gültigkeitsdauer (TTL )
  4. Konsistenzstufe
  5. SQL -basiert
  6. Diversität von NoSQL

Hier kommen Jakarta Data und Jakarta NoSQL ins Spiel.

Jakarta Data

Jakarta Data Version 1.0 wurde als Teil von Jakarta EE 11 veröffentlicht. Es bietet vereinfachten Datenzugriff auf relationale und NoSQL-Datenbanken. Es verwendet gängige Konzepte wie Repositories und benutzerdefinierte Abfragen, die aus gängigen Datenzugriffsbibliotheken wie Hibernate, Spring Data oder Micronaut Data bekannt sind. Die meisten dieser Bibliotheken unterstützen Jakarta Data oder planen dies in zukünftigen Versionen.

Schlüsselelemente der Jakarta Data API sind:

  • Archiv
  • Befehl
  • Sortieren
  • Seite

Hier ein Repository-Beispiel:

@Repository
public interface Products extends DataRepository<Product, Long> {
    List<Product> findByPriceLessThan(float maxPrice);
    void save(Product product);
    ...
}

Und wie man es benutzt:

@Inject
Products products;

products.save(new Product(1, "$25 gift card", 25.0f));

List<Product> found = products.findByPriceLessThan(100.0f);

Dasselbe kann man mit einem CrudRepository machen:

@Repository
public interface Products extends CrudRepository<Product, Long> {
    List<Product> findByPriceLessThan(float maxPrice);
    ...
}

Und erbt automatisch Methoden wie:

save(E entity);
saveAll(Iterable<E> entities);
findAll();
findById(K id);
existsById(K id);
delete(E entity);
deleteById(K id);
...

Was eine kompaktere Repository-Implementierung ermöglicht.

Ein Beispiel für die Sortierung in Verbindung mit einer dynamischen SQL Abfrage:

@Repository
public interface Products {
   Product findById(long productId);

   @OrderBy("price")
   List<Product> findByNameContains(String searchFor);


   @Query("UPDATE Product o SET o.price = o.price - (?2 * o.price) WHERE o.id = ?1")
   boolean discount(long productId, float discountRate);

   void save(Product p);
}

So wendet man Sortieren an:

gefunden = products.findByNameContains ( Namensmuster , Sort.desc ("Preis"));

Jakarta Data unterstützt sowohl Offset- als auch Cursor-Paginierung. Hier ist ein Beispiel für die versetzte Paginierung unter Verwendung eines einfachen numerischen Offsets:

@Repository
public interface BeerRepository extends BasicRepository<Beer, String> { }

Pageable page = Pageable.ofPage(1).sortBy(Sort.desc("style"));
Page<Beer> page1 = repository.findAll(page);
System.out.println("The first page:");
page1.forEach(System.out::println);

Pageable secondPage = page.next();
Page<Beer> page2 = repository.findAll(secondPage);
System.out.println("The second page:");
page2.forEach(System.out::println);

Bei der Cursor-basierten Paginierung wird anstelle eines einfachen Offsets eine Referenz verwendet, in diesem Fall ein Cursor, um Datensätze in Seiten aufzuteilen:

@Repository
public interface FruitRepository extends BasicRepository<Fruit, String> {

    @Find
    CursoredPage<Fruit> cursor(PageRequest pageRequest, Sort<Fruit> order);

}

var pageRequest = PageRequest.ofSize(size).beforeCursor(PageRequest.Cursor.forKey(before));
var page = fruitRepository.cursor(pageRequest, DESC);

Jakarta Data unterstützt außerdem Persistenz-Lebenszyklusereignisse wie:

void afterUpdate(@Observes PostUpdateEvent<Book> event) {
       // Perform post-update actions
}

Was die gleiche Funktionalität bietet, die davor oft nur mithilfe von Datenbanktriggern realisierbar war.

Jakarta NoSQL

Jakarta NoSQL startete zwar früher als das ausgegliederte Jakarta Data, veröffentlichte seine Version 1.0 jedoch im Frühjahr 2025. Der Inhalt von Jakarta EE 11 war bereits fertiggestellt, daher zielt Jakarta NoSQL 1.1 auf die Aufnahme in Jakarta EE 12 ab.

Jakarta NoSQL bietet viele Anmerkungen, die Benutzern von JPA vertraut sind, sodass es sich auch gut in Jakarta Data integrieren lässt:

AnnotationDescription
@EntityDefines a class as a persistable entity
@IdMarks the primary key of an entity
@ColumnMaps a property or field to a database column
@Embeddable, @MappedSuperclassEnable composition and inheritance
@ConvertHandles type conversion for persistence
Jakarta NoSQL Annotationen

Mithilfe der kompatiblen Implementierung Eclipse JNoSQL können Sie ein sehr ähnliches BeerRepository definieren , das wir zuvor gesehen haben, jedoch für eine NoSQL-Datenbank wie die Oracle NoSQL-Datenbank:

import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import org.eclipse.jnosql.databases.oracle.mapping.OracleNoSQLRepository;
 
@Repository
public interface BeerRepository extends OracleNoSQLRepository<Beer, String> {
 
    Set<Beer> findByStyle(String style);
 
    @Query("select * from Beer")
    Set<Beer> query();
}

Zusätzlich zum Repository unterstützt Jakarta NoSQL auch die Template- Schnittstelle, um Java-Entitäten mit NoSQL-Datenbanken zu verbinden. Über diese Vorlage können Sie Standard-CRUD-Operationen und Fluent-Abfragen mit einer konsistenten API durchführen.

Nehmen wir ein Beispiel einer Auto -Entität:

@Entity
public class Car {

    @Id
    private Long id;

    @Column
    private String name;

    @Column
    private CarType type;

    // Getters and setters...
}

Und wenden mithilfe der Vorlage einige einfache CRUD-Operationen an:

@Inject
Template template;

Car car = Car.id(1L)
             .name("Ferrari")
             .type(CarType.SPORT);

template.insert(car);

Optional<Car> result = template.find(Car.class, 1L);
template.delete(Car.class, 1L);

Zusätzlich zur grundlegenden Persistenz bietet die Template- Schnittstelle auch eine typsichere und ausdrucksstarke Fluent-Query-API:

List<Car> cars = template.select(Car.class)
                         .where("type").eq(CarType.SUV)
                         .orderBy("name").asc()
                         .result();

template.delete(Car.class)
        .where("type").eq(CarType.COUPE)
        .execute();


Unterstützte NoSQL-Datenbanktypen

Eclipse JNoSQL unterstützt derzeit die drei gängigsten Typen von NoSQL-Datenbanken: Schlüssel-Wert-, spaltenbasierte, Dokument- und Graph-Datenbanken.

Graphdatenbanken Für Graphdatenbanken baut JNoSQL auf Apache TinkerPop auf , wodurch derzeit mehr als 30 NoSQL-Datenbanken unterstützt werden.

Benutzerdefinierte Annotationen

Für einige NoSQL-Datenbanken bietet Eclipse JNoSQL benutzerdefinierte Annotationen. Hier ein Beispiel für Apache Cassandra.

Entity:

@Entity("god")
public class God {

@Column
private String name;

@UDT("weapon")
@Column
private Weapon weapon;

}

Repository:

@Repository
interface GodRepository extends CassandraRepository<God, String> {

 @CQL("select * from God where name = ?")
   List<God> findByName(String name);

}

Schlussfolgerung

Jakarta Data und Jakarta NoSQL optimieren die Integration von Java-Anwendungen mit relationalen und nicht-relationalen Datenbanken. Basierend auf aktiven und dynamischen Communities wie Eclipse oder Apache TinkerPop und unterstützt von einigen der beliebtesten Java-Persistenzbibliotheken wie Hibernate, Micronaut oder OpenLiberty , können beide Jakarta EE-Spezifikationen dazu beitragen, Ihre Datenanwendungen für eine herstellerneutrale Zukunft zu verbessern.

Total
0
Shares
Previous Post

High Speed JPA

Next Post

IntelliJ-Plugin „Save Actions“: Kontinuität durch Community-Maintenance

Related Posts