JavaRush /Java-Blog /Random-DE /JPA: Einführung in die Technologie
Viacheslav
Level 3

JPA: Einführung in die Technologie

Veröffentlicht in der Gruppe Random-DE
Die moderne Entwicklungswelt ist voll von verschiedenen Spezifikationen, die das Leben einfacher machen sollen. Wenn Sie die Werkzeuge kennen, können Sie das richtige auswählen. Ohne es zu wissen, können Sie Ihr Leben schwieriger machen. Diese Rezension wird den Schleier der Geheimhaltung über das Konzept von JPA (Java Persistence API) lüften. Ich hoffe, dass Sie nach der Lektüre noch tiefer in diese geheimnisvolle Welt eintauchen möchten.
JPA: Einführung in die Technologie – 1

Einführung

Wie wir wissen, ist die Speicherung und Verarbeitung von Daten eine der Hauptaufgaben von Programmen. In der guten alten Zeit speicherte man Daten einfach in Dateien. Sobald jedoch gleichzeitiger Lese- und Bearbeitungszugriff erforderlich ist, wird es bei Auslastung (d. h. wenn mehrere Anfragen gleichzeitig eintreffen) zum Problem, Daten einfach in Dateien zu speichern. Für weitere Informationen darüber, welche Probleme Datenbanken lösen und wie, empfehle ich Ihnen, den Artikel „ Wie Datenbanken aufgebaut sind “ zu lesen . Das bedeutet, dass wir uns dafür entscheiden, unsere Daten in einer Datenbank zu speichern. Seit langem kann Java über die JDBC-API (The Java Database Connectivity) mit Datenbanken arbeiten. Mehr über JDBC können Sie hier lesen: „ JDBC oder wo alles beginnt .“ Aber die Zeit verging und Entwickler standen jedes Mal vor der Notwendigkeit, denselben Typ und unnötigen „Wartungs“-Code (den sogenannten Boilerplate-Code) für triviale Vorgänge zum Speichern von Java-Objekten in der Datenbank und umgekehrt zu schreiben und Java-Objekte mithilfe von Daten aus der Datenbank zu erstellen Datenbank. Und um diese Probleme zu lösen, wurde ein Konzept wie ORM geboren. ORM – Objektrelationales Mapping oder ins Russische übersetztes objektrelationales Mapping. Dabei handelt es sich um eine Programmiertechnologie, die Datenbanken mit den Konzepten objektorientierter Programmiersprachen verknüpft. Vereinfacht ausgedrückt ist ORM die Verbindung zwischen Java-Objekten und Datensätzen in einer Datenbank: JPA: Einführung in die Technologie – 2ORM ist im Wesentlichen das Konzept, dass ein Java-Objekt als Daten in einer Datenbank dargestellt werden kann (und umgekehrt). Es wurde in Form der JPA-Spezifikation – Java Persistence API – verkörpert. Die Spezifikation ist bereits eine Beschreibung der Java-API, die dieses Konzept zum Ausdruck bringt. Die Spezifikation sagt uns, welche Werkzeuge uns zur Verfügung gestellt werden müssen (also über welche Schnittstellen wir arbeiten können), um nach dem ORM-Konzept arbeiten zu können. Und wie man diese Mittel verwendet. Die Spezifikation beschreibt nicht die Implementierung der Tools. Dadurch ist es möglich, unterschiedliche Implementierungen für eine Spezifikation zu verwenden. Man kann es vereinfachen und sagen, dass eine Spezifikation eine Beschreibung der API ist. Den Text der JPA-Spezifikation finden Sie auf der Oracle-Website: „ JSR 338: JavaTM Persistence API “. Um JPA nutzen zu können, benötigen wir daher eine Implementierung, mit der wir die Technologie nutzen. JPA-Implementierungen werden auch JPA-Provider genannt. Eine der bemerkenswertesten JPA-Implementierungen ist Hibernate . Daher schlage ich vor, darüber nachzudenken.
JPA: Einführung in die Technologie – 3

Ein Projekt erstellen

Da es bei JPA um Java geht, benötigen wir ein Java-Projekt. Wir könnten die Verzeichnisstruktur manuell selbst erstellen und die erforderlichen Bibliotheken selbst hinzufügen. Aber es ist viel bequemer und richtiger, Systeme zur Automatisierung der Projektmontage zu verwenden (d. h. im Wesentlichen ist dies nur ein Programm, das die Projektmontage für uns verwaltet. Erstellen Sie Verzeichnisse, fügen Sie die erforderlichen Bibliotheken zum Klassenpfad hinzu usw .). Ein solches System ist Gradle. Mehr über Gradle können Sie hier lesen: „ Eine kurze Einführung in Gradle “. Wie wir wissen, wird die Gradle-Funktionalität (d. h. die Dinge, die es tun kann) mithilfe verschiedener Gradle-Plugins implementiert. Lassen Sie uns Gradle und das Plugin „ Gradle Build Init Plugin “ verwenden. Lassen Sie uns den Befehl ausführen:

gradle init --type java-application
Gradle übernimmt für uns die notwendige Verzeichnisstruktur und erstellt eine grundlegende deklarative Beschreibung des Projekts im Build-Skript build.gradle. Wir haben also eine Bewerbung. Wir müssen darüber nachdenken, was wir mit unserer Anwendung beschreiben oder modellieren wollen. Lassen Sie uns ein Modellierungstool verwenden, zum Beispiel: app.quickdatabasediagrams.com JPA: Einführung in die Technologie – 4 Hier ist es erwähnenswert, dass es sich bei dem, was wir beschrieben haben, um unser „Domänenmodell“ handelt. Eine Domain ist ein „Themenbereich“. Im Allgemeinen bedeutet „Domäne“ im Lateinischen „Besitz“. Im Mittelalter wurden so Gebiete bezeichnet, die im Besitz von Königen oder Feudalherren waren. Und im Französischen wurde daraus das Wort „domaine“, was einfach „Gebiet“ bedeutet. So haben wir unser „Domänenmodell“ = „Subjektmodell“ beschrieben. Jedes Element dieses Modells ist eine Art „Essenz“, etwas aus dem wirklichen Leben. In unserem Fall sind dies Entitäten: Kategorie ( Category), Betreff ( Topic). Erstellen wir ein eigenes Paket für die Entitäten, zum Beispiel mit dem Namen model. Und fügen wir dort Java-Klassen hinzu, die Entitäten beschreiben. Im Java-Code sind solche Entitäten ein reguläres POJO , das so aussehen könnte:
public class Category {
    private Long id;
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
Kopieren wir den Inhalt der Klasse und erstellen wir analog eine Klasse Topic. Er wird sich nur darin unterscheiden, was er über die Kategorie weiß, zu der er gehört. Fügen wir daher Topicder Klasse ein Kategoriefeld und Methoden für die Arbeit damit hinzu:
private Category category;

public Category getCategory() {
	return category;
}

public void setCategory(Category category) {
	this.category = category;
}
Jetzt haben wir eine Java-Anwendung, die über ein eigenes Domänenmodell verfügt. Jetzt ist es an der Zeit, eine Verbindung zum JPA-Projekt herzustellen.
JPA: Einführung in die Technologie – 5

JPA hinzufügen

Wie wir uns erinnern, bedeutet JPA also, dass wir etwas in der Datenbank speichern. Deshalb brauchen wir eine Datenbank. Um eine Datenbankverbindung in unserem Projekt zu verwenden, müssen wir eine Abhängigkeitsbibliothek hinzufügen, um eine Verbindung zur Datenbank herzustellen. Wie wir uns erinnern, haben wir Gradle verwendet, das ein Build-Skript für uns erstellt hat build.gradle. Darin beschreiben wir die Abhängigkeiten, die unser Projekt benötigt. Abhängigkeiten sind jene Bibliotheken, ohne die unser Code nicht funktionieren kann. Beginnen wir mit einer Beschreibung der Abhängigkeit von der Verbindung zur Datenbank. Wir machen das genauso, wie wir es machen würden, wenn wir nur mit JDBC arbeiten würden:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
Jetzt haben wir eine Datenbank. Wir können unserer Anwendung jetzt eine Ebene hinzufügen, die für die Abbildung unserer Java-Objekte in Datenbankkonzepte (von Java bis SQL) verantwortlich ist. Wie wir uns erinnern, werden wir hierfür eine Implementierung der JPA-Spezifikation namens Hibernate verwenden:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
	implementation 'org.hibernate:hibernate-core:5.4.2.Final'
Jetzt müssen wir JPA konfigurieren. Wenn wir die Spezifikation und den Abschnitt „8.1 Persistence Unit“ lesen, wissen wir, dass eine Persistence Unit eine Art Kombination aus Konfigurationen, Metadaten und Entitäten ist. Und damit JPA funktioniert, müssen Sie in der Konfigurationsdatei mindestens eine Persistenzeinheit mit dem Namen beschreiben persistence.xml. Sein Standort ist im Spezifikationskapitel „8.2 Persistence Unit Packaging“ beschrieben. Wenn wir eine Java SE-Umgebung haben, müssen wir diese gemäß diesem Abschnitt im Stammverzeichnis des META-INF-Verzeichnisses ablegen.
JPA: Einführung in die Technologie – 6
Kopieren wir den Inhalt aus dem Beispiel, das in der JPA-Spezifikation im 8.2.1 persistence.xml fileKapitel „“ angegeben ist:
<persistence>
	<persistence-unit name="JavaRush">
        <description>Persistence Unit For test</description>
        <class>hibernate.model.Category</class>
        <class>hibernate.model.Topic</class>
    </persistence-unit>
</persistence>
Aber das reicht nicht aus. Wir müssen sagen, wer unser JPA-Anbieter ist, d. h. jemand, der die JPA-Spezifikation implementiert:
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
Jetzt fügen wir Einstellungen hinzu ( properties). Einige davon (beginnend mit javax.persistence) sind Standard-JPA-Konfigurationen und werden in der JPA-Spezifikation im Abschnitt „8.2.1.9 Eigenschaften“ beschrieben. Einige Konfigurationen sind anbieterspezifisch (in unserem Fall betreffen sie Hibernate als JPA-Anbieter. Unser Einstellungsblock sieht folgendermaßen aus:
<properties>
    <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
    <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE" />
    <property name="javax.persistence.jdbc.user" value="sa" />
    <property name="javax.persistence.jdbc.password" value="" />
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
Jetzt haben wir eine JPA-kompatible Konfiguration persistence.xml, es gibt einen JPA-Anbieter Hibernate und eine H2-Datenbank sowie zwei Klassen, die unser Domänenmodell darstellen. Lassen Sie uns endlich dafür sorgen, dass das alles klappt. Im Katalog /test/javahat unser Gradle freundlicherweise eine Vorlage für Unit-Tests generiert und sie AppTest genannt. Nutzen wir es. Wie im Kapitel „7.1 Persistenzkontexte“ der JPA-Spezifikation angegeben, leben Entitäten in der JPA-Welt in einem Raum, der Persistenzkontext genannt wird. Aber wir arbeiten nicht direkt mit Persistence Context. Hierfür verwenden wir Entity Manageroder „Entity Manager“. Er ist es, der den Kontext kennt und weiß, welche Entitäten dort leben. Wir interagieren mit Entity Manager'om. Dann bleibt nur noch zu verstehen, woher wir dieses bekommen können Entity Manager? Gemäß dem Kapitel „7.2.2 Obtaining an Application-managed Entity Manager“ der JPA-Spezifikation müssen wir verwenden EntityManagerFactory. Bewaffnen wir uns daher mit der JPA-Spezifikation und nehmen ein Beispiel aus dem Kapitel „7.3.2 Erhalten einer Entity Manager Factory in einer Java SE-Umgebung“ und formatieren es in Form eines einfachen Unit-Tests:
@Test
public void shouldStartHibernate() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	EntityManager entityManager = emf.createEntityManager();
}
Dieser Test zeigt bereits den Fehler „Unrecognized JPA persistence.xml XSD version“ an. Der Grund dafür ist, dass persistence.xmlSie das zu verwendende Schema korrekt angeben müssen, wie in der JPA-Spezifikation im Abschnitt „8.3 persistence.xml Schema“ angegeben:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">
Darüber hinaus ist die Reihenfolge der Elemente wichtig. Daher providermuss es vor dem Auflisten der Klassen angegeben werden. Danach wird der Test erfolgreich ausgeführt. Wir haben die direkte JPA-Verbindung fertiggestellt. Bevor wir fortfahren, denken wir über die verbleibenden Tests nach. Jeder unserer Tests erfordert EntityManager. Stellen wir sicher, dass jeder Test EntityManagerzu Beginn der Ausführung seinen eigenen hat. Darüber hinaus möchten wir, dass die Datenbank jedes Mal neu ist. Aufgrund der Tatsache, dass wir inmemorydie Option nutzen, reicht es aus, zu schließen EntityManagerFactory. Die Schöpfung Factoryist eine teure Operation. Aber für Tests ist es gerechtfertigt. Mit JUnit können Sie Methoden angeben, die vor (Before) und nach (After) der Ausführung jedes Tests ausgeführt werden:
public class AppTest {
    private EntityManager em;

    @Before
    public void init() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
        em = emf.createEntityManager();
    }

    @After
    public void close() {
        em.getEntityManagerFactory().close();
        em.close();
    }
Bevor nun ein Test ausgeführt wird, wird ein neuer erstellt EntityManagerFactory, was die Erstellung einer neuen Datenbank mit sich bringt, denn hibernate.hbm2ddl.autohat die Bedeutung create. Und aus der neuen Fabrik bekommen wir eine neue EntityManager.
JPA: Einführung in die Technologie – 7

Entitäten

Wie wir uns erinnern, haben wir zuvor Klassen erstellt, die unser Domänenmodell beschreiben. Wir haben bereits gesagt, dass dies unsere „Essenzen“ sind. Dies ist die Entität, die wir mit verwalten werden EntityManager. Schreiben wir einen einfachen Test, um das Wesentliche einer Kategorie zu speichern:
@Test
public void shouldPersistCategory() {
	Category cat = new Category();
	cat.setTitle("new category");
	// JUnit обеспечит тест свежим EntityManager'ом
	em.persist(cat);
}
Aber dieser Test wird nicht sofort funktionieren, weil... Wir erhalten verschiedene Fehler, die uns helfen zu verstehen, was Entitäten sind:
  • Unknown entity: hibernate.model.Category
    Warum versteht Hibernate nicht, was Categorydas ist entity? Die Sache ist, dass Entitäten gemäß dem JPA-Standard beschrieben werden müssen.
    Entitätsklassen müssen mit der Annotation annotiert werden @Entity, wie im Kapitel „2.1 Die Entitätsklasse“ der JPA-Spezifikation angegeben.

  • No identifier specified for entity: hibernate.model.Category
    Entitäten müssen über eine eindeutige Kennung verfügen, die zur Unterscheidung eines Datensatzes von einem anderen verwendet werden kann.
    Gemäß Kapitel „2.4 Primärschlüssel und Entitätsidentität“ der JPA-Spezifikation muss „jede Entität einen Primärschlüssel haben“, d. h. Jede Entität muss einen „Primärschlüssel“ haben. Ein solcher Primärschlüssel muss durch die Annotation angegeben werden@Id

  • ids for this class must be manually assigned before calling save()
    Irgendwo muss der Ausweis herkommen. Es kann manuell angegeben oder automatisch abgerufen werden.
    Daher können wir, wie in den Kapiteln „11.2.3.3 GeneratedValue“ und „11.1.20 GeneratedValue-Annotation“ angegeben, die Annotation angeben @GeneratedValue.

Damit aus der Kategorieklasse eine Entität wird, müssen wir die folgenden Änderungen vornehmen:
@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;
Darüber hinaus @Idgibt die Anmerkung an, welche verwendet werden soll Access Type. Weitere Informationen zum Zugriffstyp finden Sie in der JPA-Spezifikation im Abschnitt „2.3 Zugriffstyp“. Um es ganz kurz zu sagen, denn... Wenn wir @Idoben das Feld ( field) angegeben haben, ist der Zugriffstyp default field-basedund nicht property-based. Daher liest und speichert der JPA-Anbieter Werte direkt aus den Feldern. Wenn wir es @Idüber dem Getter platzieren würden, property-basedwürde der Zugriff verwendet werden, d. h. über Getter und Setter. Beim Ausführen des Tests sehen wir auch, welche Anfragen an die Datenbank gesendet werden (dank der Option hibernate.show_sql). Aber beim Speichern sehen wir keine insert„s“. Es stellt sich heraus, dass wir tatsächlich nichts gespart haben? Mit JPA können Sie den Persistenzkontext und die Datenbank mit der folgenden Methode synchronisieren flush:
entityManager.flush();
Aber wenn wir es jetzt ausführen, erhalten wir eine Fehlermeldung: Es ist keine Transaktion im Gange . Und jetzt ist es an der Zeit, zu erfahren, wie JPA Transaktionen nutzt.
JPA: Einführung in die Technologie – 8

JPA-Transaktionen

Wie wir uns erinnern, basiert JPA auf dem Konzept des Persistenzkontexts. Dies ist der Ort, an dem Entitäten leben. Und wir verwalten Unternehmen über EntityManager. Wenn wir den Befehl ausführen persist, platzieren wir die Entität im Kontext. Genauer gesagt sagen wir EntityManagerihnen, dass dies getan werden muss. Aber dieser Kontext ist nur ein Speicherbereich. Manchmal wird er sogar als „First-Level-Cache“ bezeichnet. Es muss jedoch mit der Datenbank verbunden sein. Der Befehl flush, der zuvor mit einem Fehler fehlschlug, synchronisiert Daten aus dem Persistenzkontext mit der Datenbank. Dafür ist aber ein Transport nötig und dieser Transport ist eine Transaktion. Transaktionen in JPA werden im Abschnitt „7.5 Transaktionen steuern“ der Spezifikation beschrieben. Für die Verwendung von Transaktionen in JPA gibt es eine spezielle API:
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
Wir müssen unserem Code Transaktionsverwaltung hinzufügen, die vor und nach Tests ausgeführt wird:
@Before
public void init() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	em = emf.createEntityManager();
	em.getTransaction().begin();
}
@After
public void close() {
	if (em.getTransaction().isActive()) {
		em.getTransaction().commit();
        }
	em.getEntityManagerFactory().close();
	em.close();
}
Nach dem Hinzufügen sehen wir im Einfügungsprotokoll einen Ausdruck in SQL, der vorher nicht vorhanden war:
JPA: Einführung in die Technologie – 9
Die in der Transaktion gesammelten Änderungen EntityManagerwurden in der Datenbank festgeschrieben (bestätigt und gespeichert). Versuchen wir nun, unsere Essenz zu finden. Erstellen wir einen Test, um nach einer Entität anhand ihrer ID zu suchen:
@Test
public void shouldFindCategory() {
	Category cat = new Category();
	cat.setTitle("test");
	em.persist(cat);
	Category result = em.find(Category.class, 1L);
	assertNotNull(result);
}
In diesem Fall erhalten wir die zuvor gespeicherte Entität, sehen die SELECT-Abfragen jedoch nicht im Protokoll. Und alles basiert auf dem, was wir sagen: „Entitätsmanager, bitte suchen Sie mir die Kategorie-Entität mit der ID=1.“ Und der Entitätsmanager sucht zunächst in seinem Kontext (verwendet eine Art Cache), und erst wenn er ihn nicht findet, sucht er in der Datenbank. Es lohnt sich, die ID auf 2 zu ändern (so etwas gibt es nicht, wir haben nur 1 Instanz gespeichert), und wir werden sehen, dass SELECTdie Anfrage erscheint. Da im Kontext keine Entitäten gefunden wurden und EntityManagerdie Datenbank versucht, eine Entität zu finden, gibt es verschiedene Befehle, mit denen wir den Status einer Entität im Kontext steuern können. Der Übergang einer Entität von einem Zustand in einen anderen wird als Lebenszyklus der Entität bezeichnet lifecycle.
JPA: Einführung in die Technologie – 10

Entitätslebenszyklus

Der Lebenszyklus von Entitäten wird in der JPA-Spezifikation im Kapitel „3.2 Lebenszyklus der Entitätsinstanz“ beschrieben. Weil Entitäten leben in einem Kontext und werden von kontrolliert EntityManager, dann sagt man, dass Entitäten kontrolliert werden, d. h. gelang es. Schauen wir uns die Phasen im Leben eines Wesens an:
// 1. New oder Transient (временный)
Category cat = new Category();
cat.setTitle("new category");
// 2. Managed oder Persistent
entityManager.persist(cat);
// 3. Транзакция завершена, все сущности в контексте detached
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
// 4. Сущность изымаем из контекста, она становится detached
entityManager.detach(cat);
// 5. Сущность из detached можно снова сделать managed
Category managed = entityManager.merge(cat);
// 6. И можно сделать Removed. Интересно, что cat всё равно detached
entityManager.remove(managed);
Und hier ist ein Diagramm zur Konsolidierung:
JPA: Einführung in die Technologie – 11
JPA: Einführung in die Technologie – 12

Kartierung

In JPA können wir die Beziehungen von Entitäten untereinander beschreiben. Erinnern wir uns daran, dass wir uns bereits mit den Beziehungen von Entitäten untereinander befasst haben, als wir uns mit unserem Domänenmodell befassten. Dann haben wir die Ressource quickdatabasediagrams.com verwendet :
JPA: Einführung in die Technologie – 13
Das Herstellen von Verbindungen zwischen Entitäten wird als Mapping oder Assoziation (Association Mappings) bezeichnet. Die Arten von Assoziationen, die mit JPA hergestellt werden können, werden im Folgenden vorgestellt:
JPA: Einführung in die Technologie – 14
Schauen wir uns eine Entität an Topic, die ein Thema beschreibt. Was können wir über die Einstellung Topicdazu sagen Category? Viele Topicwerden zu einer Kategorie gehören. Deshalb brauchen wir einen Verein ManyToOne. Lassen Sie uns diese Beziehung in JPA ausdrücken:
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
Um sich zu merken, welche Anmerkungen Sie einfügen müssen, können Sie sich merken, dass der letzte Teil für das Feld verantwortlich ist, über dem die Anmerkung angegeben ist. ToOne- konkrete Instanz. ToMany- Sammlungen. Jetzt ist unsere Verbindung einseitig. Machen wir es zu einer wechselseitigen Kommunikation. Lassen Sie uns Categorydas Wissen über jeden erweitern Topic, der in dieser Kategorie enthalten ist. Es muss mit enden ToMany, da wir eine Liste haben Topic. Das heißt, die Einstellung „Zu vielen“ Themen. Bleibt die Frage – OneToManyoder ManyToMany:
JPA: Einführung in die Technologie – 15
Eine gute Antwort zum gleichen Thema kann hier gelesen werden: „ Erklären Sie die ORM-OneToMany-, ManyToMany-Beziehung, als wäre ich fünf “. Wenn eine Kategorie einen Zusammenhang mit Themen hat , dann kann jedes dieser Themen nur eine Kategorie haben, andernfalls ToManyist es . Die Liste aller Themen sieht also folgendermaßen aus:OneManyCategory
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "topic_id")
private Set<Topic> topics = new HashSet<>();
Und vergessen wir nicht, im Wesentlichen Categoryeinen Getter zu schreiben, um eine Liste aller Themen zu erhalten:
public Set<Topic> getTopics() {
	return this.topics;
}
Bidirektionale Beziehungen lassen sich nur sehr schwer automatisch nachverfolgen. Daher verlagert JPA diese Verantwortung auf den Entwickler. Für uns bedeutet dies, dass wir beim Aufbau einer Entitätsbeziehung Topicmit Categorydie Datenkonsistenz selbst sicherstellen müssen. Das geht ganz einfach:
public void setCategory(Category category) {
	category.getTopics().add(this);
	this.category = category;
}
Schreiben wir einen einfachen Test, um Folgendes zu überprüfen:
@Test
public void shouldPersistCategoryAndTopics() {
	Category cat = new Category();
	cat.setTitle("test");
	Topic topic = new Topic();
	topic.setTitle("topic");
	topic.setCategory(cat);
 	em.persist(cat);
}
Mapping ist ein ganz anderes Thema. Der Zweck dieser Überprüfung besteht darin, die Mittel zu verstehen, mit denen dies erreicht wird. Weitere Informationen zum Mapping finden Sie hier:
JPA: Einführung in die Technologie – 16

JPQL

JPA führt ein interessantes Tool ein – Abfragen in der Java Persistence Query Language. Diese Sprache ähnelt SQL, verwendet jedoch das Java-Objektmodell anstelle von SQL-Tabellen. Schauen wir uns ein Beispiel an:
@Test
public void shouldPerformQuery() {
	Category cat = new Category();
	cat.setTitle("query");
	em.persist(cat);
	Query query = em.createQuery("SELECT c from Category c WHERE c.title = 'query'");
 	assertNotNull(query.getSingleResult());
}
Wie wir sehen können, haben wir in der Abfrage einen Verweis auf eine Entität Categoryund nicht auf eine Tabelle verwendet. Und auch auf dem Gebiet dieser Entität title. JPQL bietet viele nützliche Funktionen und verdient einen eigenen Artikel. Weitere Details finden Sie im Testbericht:
JPA: Einführung in die Technologie – 17

Kriterien-API

Abschließend möchte ich noch auf die Criteria API eingehen. JPA führt ein dynamisches Abfrageerstellungstool ein. Beispiel für die Verwendung der Kriterien-API:
@Test
public void shouldFindWithCriteriaAPI() {
	Category cat = new Category();
	em.persist(cat);
	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<Category> query = cb.createQuery(Category.class);
	Root<Category> c = query.from(Category.class);
	query.select(c);
	List<Category> resultList = em.createQuery(query).getResultList();
	assertEquals(1, resultList.size());
}
Dieses Beispiel entspricht der Ausführung der Anfrage „ SELECT c FROM Category c“. Die Criteria API ist ein leistungsstarkes Tool. Mehr dazu können Sie hier lesen:

Abschluss

Wie wir sehen, bietet JPA eine Vielzahl von Funktionen und Tools. Jeder von ihnen erfordert Erfahrung und Wissen. Selbst im Rahmen des JPA-Reviews war es nicht möglich, alles zu erwähnen, geschweige denn einen detaillierten Tauchgang. Aber ich hoffe, dass nach der Lektüre klarer geworden ist, was ORM und JPA sind, wie es funktioniert und was man damit machen kann. Nun, für einen Snack biete ich verschiedene Materialien an: #Wjatscheslaw
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION