Was ist JPA? Einführung in die Java Persistence API

Als Spezifikation befasst sich die Java Persistence API mit Persistenz, was lose jeden Mechanismus bedeutet, durch den Java-Objekte den Anwendungsprozess überleben, der sie erstellt hat. Nicht alle Java-Objekte müssen beibehalten werden, aber die meisten Anwendungen behalten wichtige Geschäftsobjekte bei. Mit der JPA-Spezifikation können Sie definieren, welche Objekte beibehalten werden sollen und wie diese Objekte in Ihren Java-Anwendungen beibehalten werden sollen.

An sich ist JPA kein Werkzeug oder Framework; vielmehr definiert es eine Reihe von Konzepten, die von jedem Tool oder Framework implementiert werden können. Während das objektrelationale Mapping-Modell (ORM) von JPA ursprünglich auf Hibernate basierte, hat es sich seitdem weiterentwickelt. Während JPA ursprünglich für die Verwendung mit relationalen / SQL-Datenbanken vorgesehen war, wurden einige JPA-Implementierungen für die Verwendung mit NoSQL-Datenspeichern erweitert. Ein beliebtes Framework, das JPA mit NoSQL unterstützt, ist EclipseLink, die Referenzimplementierung für JPA 2.2.

JPA und Hibernate

Aufgrund ihrer verflochtenen Historie werden Hibernate und JPA häufig zusammengeführt. Wie die Java-Servlet-Spezifikation hat JPA jedoch viele kompatible Tools und Frameworks hervorgebracht.

Hibernate wurde von Gavin King entwickelt und Anfang 2002 veröffentlicht und ist eine ORM-Bibliothek für Java. King entwickelte Hibernate als Alternative zu Entity Beans für die Persistenz. Das Framework war zu dieser Zeit so beliebt und so notwendig, dass viele seiner Ideen in der ersten JPA-Spezifikation übernommen und kodifiziert wurden.

Heute ist Hibernate ORM eine der ausgereiftesten JPA-Implementierungen und immer noch eine beliebte Option für ORM in Java. Ruhezustand ORM 5.3.8 (die aktuelle Version zum Zeitpunkt des Schreibens) implementiert JPA 2.2. Darüber hinaus wurde die Toolfamilie von Hibernate um beliebte Tools wie Hibernate Search, Hibernate Validator und Hibernate OGM erweitert, die die Domänenmodellpersistenz für NoSQL unterstützen.

Was ist Java ORM?

Während sie sich in der Ausführung unterscheiden, bietet jede JPA-Implementierung eine Art ORM-Schicht. Um JPA und JPA-kompatible Tools zu verstehen, müssen Sie ORM gut verstehen.

Objektrelationales Mapping ist eine Aufgabe, die Entwickler aus gutem Grund manuell vermeiden sollten. Ein Framework wie Hibernate ORM oder EclipseLink kodifiziert diese Aufgabe in einer Bibliothek oder einem Framework, einer ORM-Ebene. Als Teil der Anwendungsarchitektur ist die ORM-Schicht für die Verwaltung der Konvertierung von Softwareobjekten verantwortlich, um mit den Tabellen und Spalten in einer relationalen Datenbank zu interagieren. In Java konvertiert der ORM-Layer Java-Klassen und -Objekte, sodass sie in einer relationalen Datenbank gespeichert und verwaltet werden können.

Standardmäßig wird der Name des Objekts, das beibehalten wird, zum Namen der Tabelle, und Felder werden zu Spalten. Sobald die Tabelle eingerichtet ist, entspricht jede Tabellenzeile einem Objekt in der Anwendung. Die Objektzuordnung ist konfigurierbar, aber die Standardeinstellungen funktionieren in der Regel gut.

Abbildung 1 veranschaulicht die Rolle von JPA und der ORM-Schicht in der Anwendungsentwicklung.

JavaWorld / IDG

Abbildung 1. JPA und die ORM-Ebene

Konfigurieren der Java-ORM-Ebene

Wenn Sie ein neues Projekt für die Verwendung von JPA einrichten, müssen Sie den Datenspeicher und den JPA-Anbieter konfigurieren. Sie konfigurieren einen Datenspeicher-Connector für die Verbindung mit der ausgewählten Datenbank (SQL oder NoSQL). Sie werden auch den JPA-Anbieter einschließen und konfigurieren, bei dem es sich um ein Framework wie Hibernate oder EclipseLink handelt. Während Sie JPA manuell konfigurieren können, verwenden viele Entwickler die sofort einsatzbereite Unterstützung von Spring. Siehe „JPA Installation und Setup“ unten für eine Demonstration der manuellen und Spring-basierten JPA Installation und Setup.

Datenpersistenz in Java

Aus Sicht der Programmierung ist die ORM-Schicht eine Adapterschicht: es passt die Sprache von Objektgraphen an die Sprache von SQL und relationalen Tabellen an. Die ORM-Schicht ermöglicht es objektorientierten Entwicklern, Software zu erstellen, die Daten persistiert, ohne jemals das objektorientierte Paradigma zu verlassen.

Wenn Sie JPA verwenden, erstellen Sie eine Zuordnung aus dem Datenspeicher zu den Datenmodellobjekten Ihrer Anwendung. Anstatt zu definieren, wie Objekte gespeichert und abgerufen werden, definieren Sie die Zuordnung zwischen Objekten und Ihrer Datenbank und rufen dann JPA auf, um sie beizubehalten. Wenn Sie eine relationale Datenbank verwenden, wird ein Großteil der tatsächlichen Verbindung zwischen Ihrem Anwendungscode und der Datenbank von JDBC, der Java Database Connectivity API, abgewickelt.

Als Spezifikation stellt JPA Metadaten-Annotationen bereit, mit denen Sie die Zuordnung zwischen Objekten und der Datenbank definieren. Jede JPA-Implementierung bietet eine eigene Engine für JPA-Annotationen. Die JPA-Spezifikation enthält auch die PersistanceManager oder EntityManager , die die wichtigsten Kontaktpunkte mit dem JPA-System darstellen (wobei Ihr Geschäftslogikcode dem System mitteilt, was mit den zugeordneten Objekten zu tun ist).

Um all dies konkreter zu machen, sollten Sie Listing 1 in Betracht ziehen, eine einfache Datenklasse zum Modellieren eines Musikers.

Auflistung 1. Eine einfache Datenklasse in Java

Die Musician Klasse in Listing 1 wird zum Speichern von Daten verwendet. Es kann primitive Daten wie das Feld name enthalten. Es kann auch Beziehungen zu anderen Klassen wie mainInstrument und performances .

Musician Der Grund dafür ist, Daten zu enthalten. Diese Art von Klasse wird manchmal als DTO oder Datenübertragungsobjekt bezeichnet. DTOs sind ein gemeinsames Merkmal der Softwareentwicklung. Sie enthalten zwar viele Arten von Daten, enthalten jedoch keine Geschäftslogik. Persistente Datenobjekte sind eine allgegenwärtige Herausforderung in der Softwareentwicklung.

Datenpersistenz mit JDBC

Eine Möglichkeit, eine Instanz der Musician -Klasse in einer relationalen Datenbank zu speichern, wäre die Verwendung der JDBC-Bibliothek. JDBC ist eine Abstraktionsebene, mit der eine Anwendung SQL-Befehle ausgeben kann, ohne über die zugrunde liegende Datenbankimplementierung nachzudenken.

Listing 2 zeigt, wie Sie die Musician Klasse mit JDBC beibehalten können.

Auflistung 2. JDBC Einfügen eines Datensatzes

Der Code in Listing 2 ist ziemlich selbstdokumentierend. Das georgeHarrison -Objekt kann von überall kommen (Front-End-Submit, externer Service usw.), und hat seine ID und name Felder gesetzt. Die Felder des Objekts werden dann verwendet, um die Werte einer SQL insert -Anweisung bereitzustellen. (Die PreparedStatement -Klasse ist Teil von JDBC und bietet eine Möglichkeit, Werte sicher auf eine SQL-Abfrage anzuwenden.)

Während JDBC die Steuerung ermöglicht, die mit der manuellen Konfiguration einhergeht, ist sie im Vergleich zu JPA umständlich. Um die Datenbank zu ändern, müssen Sie zunächst eine SQL-Abfrage erstellen, die von Ihrem Java-Objekt den Tabellen in einer relationalen Datenbank zugeordnet wird. Sie müssen dann die SQL ändern, wenn sich eine Objektsignatur ändert. Mit JDBC wird die Pflege der SQL zu einer eigenständigen Aufgabe.

Datenpersistenz mit JPA

Betrachten Sie nun Listing 3, wo wir die Musician Klasse mit JPA beibehalten.

Auflistung 3. George Harrison mit JPA beibehalten

Musician georgeHarrison = new Musician(0, "George Harrison");musicianManager.save(georgeHarrison);

Listing 3 ersetzt das manuelle SQL aus Listing 2 durch eine einzelne Zeile, session.save() , die JPA anweist, das Objekt beizubehalten. Von da an wird die SQL-Konvertierung vom Framework übernommen, sodass Sie das objektorientierte Paradigma nie mehr verlassen müssen.

Metadaten-Annotationen in JPA

Die Magie in Listing 3 ist das Ergebnis einer Konfiguration, die mit den Annotationen von JPA erstellt wird. Entwickler verwenden Anmerkungen, um JPA mitzuteilen, welche Objekte beibehalten werden sollen und wie sie beibehalten werden sollen.

Listing 4 zeigt die Musician -Klasse mit einer einzelnen JPA-Annotation.

Auflistung 4. Die @Entity Annotation von JPA

@Entitypublic class Musician { // ..class body}

Persistente Objekte werden manchmal als Entitäten bezeichnet. Das Anhängen von @Entity an eine Klasse wie Musician informiert JPA, dass diese Klasse und ihre Objekte beibehalten werden sollen.

Konfigurieren von JPA

Wie die meisten modernen Frameworks umfasst JPA Coding by Convention (auch bekannt als Convention over Configuration), bei dem das Framework eine Standardkonfiguration basierend auf Best Practices der Branche bereitstellt. Als ein Beispiel würde eine Klasse mit dem Namen Musician standardmäßig einer Datenbanktabelle mit dem Namen Musician zugeordnet.

Die herkömmliche Konfiguration spart Zeit und funktioniert in vielen Fällen gut genug. Es ist auch möglich, Ihre JPA-Konfiguration anzupassen. Als Beispiel könnten Sie die Annotation @Table von JPA verwenden, um die Tabelle anzugeben, in der die Klasse Musician gespeichert werden soll.

Auflistung 5. Die @Table Annotation von JPA

@Entity@Table(name="musician")public class Musician { // ..class body}

Listing 5 weist JPA an, die Entität (Musician Klasse) in der musician Tabelle beizubehalten.

Primärschlüssel

In JPA ist der Primärschlüssel das Feld, mit dem jedes Objekt in der Datenbank eindeutig identifiziert wird. Der Primärschlüssel ist nützlich, um Objekte mit anderen Entitäten zu referenzieren und zu verknüpfen. Wenn Sie ein Objekt in einer Tabelle speichern, geben Sie auch das Feld an, das als Primärschlüssel verwendet werden soll.

In Listing 6 teilen wir JPA mit, welches Feld als Primärschlüssel von Musician verwendet werden soll.

Auflistung 6. Angeben des Primärschlüssels

@Entitypublic class Musician { @Id private Long id;

In diesem Fall haben wir die Annotation @Id von JPA verwendet, um das Feld id als Primärschlüssel von Musician anzugeben. Standardmäßig geht diese Konfiguration davon aus, dass der Primärschlüssel von der Datenbank festgelegt wird, z. B. wenn das Feld in der Tabelle automatisch inkrementiert wird.

JPA unterstützt andere Strategien zum Generieren des Primärschlüssels eines Objekts. Es hat auch Anmerkungen zum Ändern einzelner Feldnamen. Im Allgemeinen ist JPA flexibel genug, um sich an jede Persistenzzuordnung anzupassen, die Sie möglicherweise benötigen.

CRUD-Operationen

Sobald Sie eine Klasse einer Datenbanktabelle zugeordnet und ihren Primärschlüssel festgelegt haben, haben Sie alles, was Sie zum Erstellen, Abrufen, Löschen und Aktualisieren dieser Klasse in der Datenbank benötigen. Durch Aufrufen von session.save() wird die angegebene Klasse erstellt oder aktualisiert, je nachdem, ob das Primärschlüsselfeld null ist oder auf eine vorhandene Entität zutrifft. Der Aufruf von entityManager.remove() löscht die angegebene Klasse.

Entitätsbeziehungen in JPA

Das einfache Beibehalten eines Objekts mit einem primitiven Feld ist nur die halbe Gleichung. JPA hat auch die Fähigkeit, Entitäten in Beziehung zueinander zu verwalten. In Tabellen und Objekten sind vier Arten von Entitätsbeziehungen möglich:

    1. Eins-zu-Viele
    2. Viele-zu-Eins
    3. Viele-zu-Viele
    4. Eins-zu-Eins

Jede Art von Beziehung beschreibt, wie sich eine Entität auf andere Entitäten bezieht. Beispielsweise könnte die Entität Musician eine Eins-zu-Viele-Beziehung zu Performance haben, einer Entität, die durch eine Sammlung wie List oder Set dargestellt wird.

Wenn das Musician ein Band -Feld enthielt, könnte die Beziehung zwischen diesen Entitäten viele zu eins sein, was eine Sammlung von Musicians in der einzelnen Band -Klasse impliziert. (Angenommen, jeder Musiker tritt nur in einer einzigen Band auf.)

Wenn Musician ein BandMates Feld enthält, könnte dies eine Viele-zu-Viele-Beziehung zu anderen Musician Entitäten darstellen.

Schließlich könnte Musician eine Eins-zu-Eins-Beziehung zu einer Quote Entität haben, die verwendet wird, um ein berühmtes Zitat darzustellen: Quote famousQuote = new Quote().

Beziehungstypen definieren

JPA verfügt über Anmerkungen für jeden seiner Beziehungszuordnungstypen. Listing 7 zeigt, wie Sie die Eins-zu-Viele-Beziehung zwischen Musician und Performances kommentieren können.

Listing 7. Annotieren einer Eins-zu-Viele-Beziehung

Eine Sache zu beachten ist, dass die @JoinColumn JPA mitteilt, welche Spalte in der Leistungstabelle der Musician Entität zugeordnet wird. Jede Performance wird einer einzelnen Musician zugeordnet, die von dieser Spalte verfolgt wird. Wenn JPA ein Musician oder ein Performance in die Datenbank lädt, verwendet es diese Informationen, um das Objektdiagramm wiederherzustellen.

Abrufstrategien in JPA

JPA muss nicht nur wissen, wo verwandte Entitäten in der Datenbank abgelegt werden sollen, sondern auch, wie sie geladen werden sollen. Abrufstrategien teilen JPA mit, wie verwandte Entitäten geladen werden sollen. Beim Laden und Speichern von Objekten muss ein JPA-Framework die Möglichkeit bieten, die Handhabung von Objektdiagrammen zu optimieren. Wenn zum Beispiel die Musician -Klasse ein bandMate -Feld hat (wie in Listing 7 gezeigt), könnte das Laden von george dazu führen, dass die gesamte Musician-Tabelle aus der Datenbank geladen wird!

Was benötigt wird, ist die Fähigkeit, Lazy Loading von verwandten Entitäten zu definieren – natürlich zu erkennen, dass Beziehungen in JPA eifrig oder faul sein können. Sie können Anmerkungen verwenden, um Ihre Abrufstrategien anzupassen, aber die Standardkonfiguration von JPA funktioniert häufig sofort und ohne Änderungen:

  1. One-to-many: Lazy
  2. Many-to-one: Eager
  3. Many-to-many: Lazy
  4. One-to-one: Eager

JPA-Installation und -Einrichtung

Wir schließen mit einem kurzen Blick auf die Installation und Einrichtung von JPA für Ihre Java-Anwendungen. Für diese Demonstration verwende ich EclipseLink, die JPA-Referenzimplementierung.

Die übliche Methode zur Installation von JPA besteht darin, einen JPA-Anbieter in Ihr Projekt aufzunehmen. Listing 8 zeigt, wie Sie EclipseLink als Abhängigkeit in Ihre Maven pom.xml -Datei aufnehmen würden.

Auflistung 8. EclipseLink als Maven-Abhängigkeit einschließen

org.eclipse.persistenceeclipselink2.5.0-RC1

Sie müssen auch den Treiber für Ihre Datenbank einschließen, wie in Listing 9 gezeigt.

Auflistung 9. Maven-Abhängigkeit für einen MySQL-Connector

mysqlmysql-connector-java5.1.32

Als nächstes müssen Sie dem System Ihre Datenbank und Ihren Provider mitteilen. Dies geschieht in der Datei persistence.xml, wie in Listing 10 gezeigt.

Auflistung 10. Persistenz.xml

Es gibt andere Möglichkeiten, diese Informationen dem System zur Verfügung zu stellen, auch programmgesteuert. Ich empfehle die Verwendung der Datei persistence.xml, da das Speichern von Abhängigkeiten auf diese Weise das Aktualisieren Ihrer Anwendung ohne Änderung des Codes sehr einfach macht.

Spring-Konfiguration für JPA

Die Verwendung von Spring erleichtert die Integration von JPA in Ihre Anwendung erheblich. Wenn Sie beispielsweise die Annotation @SpringBootApplication in Ihrem Anwendungsheader platzieren, wird Spring angewiesen, automatisch nach Klassen zu suchen und die EntityManager nach Bedarf basierend auf der von Ihnen angegebenen Konfiguration einzufügen.

Listing 11 zeigt die Abhängigkeiten, die Sie einschließen müssen, wenn Sie Spring’s JPA-Unterstützung für Ihre Anwendung wünschen.

Auflistung 11. Hinzufügen von Spring JPA-Unterstützung in Maven

Fazit

Jede Anwendung, die sich mit einer Datenbank befasst, sollte eine Anwendungsschicht definieren, deren einziger Zweck darin besteht, Persistenzcode zu isolieren. Wie Sie in diesem Artikel gesehen haben, führt die Java Persistence API eine Reihe von Funktionen und Unterstützung für Java Object Persistence ein. Einfache Anwendungen erfordern möglicherweise nicht alle Funktionen von JPA, und in einigen Fällen ist der Aufwand für die Konfiguration des Frameworks möglicherweise nicht angemessen. Wenn eine Anwendung jedoch wächst, verdienen die Struktur und Kapselung von JPA wirklich ihren Unterhalt. Die Verwendung von JPA hält Ihren Objektcode einfach und bietet ein herkömmliches Framework für den Zugriff auf Daten in Java-Anwendungen.

Erfahren Sie mehr über die Java Persistence API und verwandte Technologien

  • Was ist JDBC? Einführung in die Java-Datenbankkonnektivität: Lernen Sie die Low-Level-API von Java zum Herstellen einer Verbindung zu einer Datenbank, zum Ausgeben von SQL-Abfragen und mehr kennen.
  • Java Persistence mit JPA und Hibernate, Teil 1: Entitäten und Beziehungen: Beginnen Sie mit der Modellierung von Entitäten und Beziehungen mit Java 8 und Hibernate ORM.
  • Java Persistence mit JPA und Hibernate, Teil 2: Praktische Übung zum Modellieren von Many-to-Many-Beziehungen und Vererbungsbeziehungen in Java 8 und Hibernate ORM.
  • Implementieren von zustandsabhängigem Verhalten: Eine klassische Einführung in das Zustandsmuster und die Zustandsabhängigkeit in Java.
  • Eifriges / verzögertes Laden im Ruhezustand: Wie man eifriges und verzögertes Laden im Ruhezustand anwendet.
  • JPA 2.2 bringt einige mit Spannung erwartete Änderungen mit sich: Eine Übersicht über Spezifikationsaktualisierungen in JPA 2.2, einschließlich Verbesserungen an CDI, einer besseren Ausrichtung an der Datums- und UHRZEITAPI und Unterstützung für @Repeatable Anmerkungen.
  • Sollten Sie JPA für Ihr nächstes Projekt verwenden?: Schlüsselfragen, die Ihnen bei der Entscheidung helfen könnten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.