Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen `query()` und `nativeQuery()` | Grundlagen von Hibernate
Java-Datenmanipulation mit Hibernate
course content

Kursinhalt

Java-Datenmanipulation mit Hibernate

Java-Datenmanipulation mit Hibernate

1. JDBC-Übersicht
2. Grundlagen von Hibernate
3. Letzte Feinabstimmungen

book
`query()` und `nativeQuery()`

Wie wir aus den vorherigen Kapiteln gelernt haben, haben wir "eingebaute Methoden" für die Arbeit mit Entitäten. Diese Methoden befinden sich innerhalb der Session. Aber was, wenn wir eine spezifische Abfrage schreiben müssen? Zum Beispiel möchten wir nur die Mitarbeiter abrufen, die im Jahr 2023 eingestellt wurden. Für eine solche Abfrage haben wir keine eingebaute Funktion in der Session. Wir können dies jedoch mit einer SQL-Abfrage tun. Es wird so aussehen:

Hinweis

Ja, Sie können hier den BETWEEN-Operator verwenden, aber ich mag diese Funktion wirklich nicht. Sie können die Abfrage schreiben, wie Sie möchten, solange sie korrekt funktioniert.

Großartig, jetzt müssen wir verstehen, wie wir dies im Code implementieren. Wenn Sie sich die Tests im vorherigen Kapitel angesehen haben und gesehen haben, wie sie funktionieren, haben Sie vielleicht bemerkt, dass ich eine Methode des session-Objekts namens createNativeQuery() verwendet habe.

Jetzt werden wir mehr über diese Methode sprechen.

Native Query

Die Methode createNativeQuery() erstellt eine SQL-Abfrage, die bestehen bleibt, bis executeUpdate() oder executeQuery() aufgerufen wird. Schauen wir uns ein Beispiel an, bei dem wir Mitarbeiter abrufen müssen, die innerhalb eines bestimmten Zeitrahmens eingestellt wurden.

Zuerst müssen wir diese Methode zur DAO-Schnittstelle hinzufügen:

Wie Sie sehen können, verwenden wir 2 Parameter vom Typ Date, um den genauen Zeitraum anzugeben, an dem wir interessiert sind. Nun lassen Sie uns zur Implementierungsklasse übergehen und diese Methode implementieren.

Dafür müssen wir:

  1. Eine session öffnen;
  2. Eine SQL-Abfrage schreiben;
  3. Die Methode createNativeQuery() verwenden, bei der wir diese Abfrage verwenden;
  4. Daten aus den Parametern zu diesen Abfragen hinzufügen, um den Zeitraum anzugeben;
  5. Die Methode getResultList() verwenden, um Daten aus der Abfrage abzurufen;
  6. Die Abfrage ausführen und das Ergebnis in einer List speichern;
  7. Mögliche Fehler abfangen und die Sitzung schließen.

Insgesamt ist das Verfahren sehr ähnlich zu dem, das wir zuvor durchgeführt haben. Nur hier verwenden wir eine vollwertige SQL-Abfrage, um mit der Datenbank zu interagieren. Wir haben diese Abfrage nur leicht bearbeitet, um dort Parameter festzulegen. Nun, lassen Sie uns wiederholen:

Wenn wir einige Parameter in der SQL-Abfrage festlegen möchten, schreiben wir einen Platzhalter für diese Parameter direkt in die Abfrage, anstatt die Parameter direkt einzufügen.

Dafür verwenden wir die folgende Syntax:

Danach verwenden wir die Methode setParameter(), bei der wir die folgende Syntax verwenden:

Auf diese Weise ersetzt Hibernate automatisch Daten aus den Methodenparametern (oder anderen Daten) direkt in die SQL-Abfrage.

Dann rufen wir eine Liste mit dem Typ Employee ab, indem wir die Methode getResultList() verwenden.

Hinweis

Die Methode getResultList() gibt eine Liste mit dem Typ zurück, den wir in der Methode createNativeQuery() angegeben haben. Wir haben Employee.class verwendet, daher wird die zurückgegebene Liste diesen Typ haben. Wenn wir beispielsweise eine Liste von Namen abrufen möchten, verwenden wir String.class in den Parametern.

Dann folgt alles dem Algorithmus, Fehler werden abgefangen und die Sitzung wird geschlossen.

HQL

Hibernate hat seine eigene Abfragesprache, die wir ebenfalls verwenden können. Sie heißt HQL (Hibernate Query Language).

HQL ist eine bequemere Abfragesprache als SQL im Kontext ihrer Verwendung im Code, aber Sie können jede Sprache verwenden, die Sie für bequem halten.

Lassen Sie uns die wichtigsten Vorteile und Unterschiede zu SQL betrachten:

  • Objektorientierter Ansatz: HQL arbeitet mit Objekten und deren Eigenschaften, während SQL mit Tabellen und Spalten arbeitet. Das bedeutet, dass Sie in HQL auf Klassen und Felder im Java-Code verweisen, während Sie in SQL auf tatsächliche Tabellen- und Spaltennamen in der Datenbank verweisen;
  • Plattformunabhängigkeit: HQL isoliert die Anwendung von der Abhängigkeit von einer bestimmten Datenbank. Sie können zwischen verschiedenen DBMS wechseln, ohne HQL-Abfragen zu ändern, während SQL-Abfragen möglicherweise Änderungen erfordern, da verschiedene DBMS Unterschiede in Syntax und Funktionen aufweisen können;
  • Navigieren von Assoziationen: In HQL ist es einfach, durch assoziierte Objekte über ihre Assoziationen zu navigieren, während Sie in SQL Tabellen-Joins verwenden müssen;
  • Typsicherheit: HQL bietet Typsicherheit, da es Java-Klassen und -Eigenschaften verwendet, wodurch die Wahrscheinlichkeit von Fehlern im Zusammenhang mit Datentypen verringert wird.

Vergleichen wir Abfragen in SQL und HQL, um den Unterschied zwischen diesen beiden Abfragesprachen zu sehen:

SQL-Abfrage für die Auswahl:

Äquivalente HQL-Abfrage:

SQL-Abfrage mit JOIN:

Äquivalente HQL-Abfrage:

SQL-Abfrage für Update:

Äquivalente HQL-Abfrage:

In diesen Beispielen kann man sehen, dass HQL das SELECT-Schlüsselwort nicht verwendet, um Objekte auszuwählen und auf Eigenschaften mit Punkten zuzugreifen, während SQL mit tatsächlichen Spaltennamen arbeitet und die Verwendung des SELECT-Schlüsselworts erfordert.

HQL bietet größere Flexibilität und Leistung für das objektorientierte Modell bei der Arbeit mit Datenbanken und bietet eine Vielzahl von Funktionen, um die Entwicklung zu vereinfachen, wie z.B. Paginierung, benannte Abfragen und Integration mit Caching.

Abfrage

Um HQL zu verwenden, sollten wir die Methode createQuery() anstelle von createNativeQuery() verwenden.

Lassen Sie uns die zuvor geschriebene Methode ändern, um HQL zu integrieren:

Wie Sie sehen können, hat sich etwas Code geändert. Jetzt verwenden wir das Query-Interface anstelle von NativeQuery. Diese Schnittstellen haben fast identische Methoden, sodass wir die Abfrage nicht viel bearbeiten mussten. Auf diese Weise arbeiten wir mit Objekten und sehen klar, welche Objekte aus den Tabellen abgerufen werden.

Aber woher weiß Hibernate, mit welcher Tabelle es arbeiten soll? Hibernate schaut sich die Entity-Klasse an und sieht welche Tabelle dort angegeben ist und die entsprechenden Spalten dieser Tabelle. Auf diese Weise ersetzt es automatisch die notwendigen Daten und führt die Abfrage aus.

Implementierung der Service-Schicht

Lassen Sie uns die vollständige Implementierung der Methode abschließen und die Methode getEmployeesHiredInASpecificTimeframe() in der Service-Schicht implementieren.

Zuerst müssen wir eine solche Methode im EmployeeService-Interface erstellen:

Wie Sie sehen können, haben wir eine zusätzliche Methode hinzugefügt, die nur employee-Namen abruft. Ähnlich wie zuvor sollte eine solche Methode in der Service-Schicht platziert werden.

Schauen wir uns nun die Implementierung an:

Insgesamt wird solcher Code funktionieren, aber es gibt eine wesentliche Einschränkung. Es wird sehr unpraktisch für uns sein, mit einer Klasse wie Date() zu arbeiten, da sie kein für uns bequemes Format akzeptiert. Lassen Sie uns die LocalDate-Klasse verwenden, die in Java 8 eingeführt wurde, um einen private Parser zu schreiben, der das Datum aus einem String-Format "yyyy-mm-dd" in ein Date-Objekt umwandelt, was es für uns und den Benutzer bequemer macht, mit Methoden zu arbeiten:

Dieser Code wird das Datum automatisch von String zu Date parsen.

Lassen Sie uns aufschlüsseln, wie es funktioniert:

  1. Wir erstellen ein formatter-Objekt der Klasse DateTimeFormatter, in dem wir das Muster angeben, nach dem das Datum geparst wird;
  2. Dann speichern wir ein solches Datum in einer Variablen vom Typ LocalDate, indem wir die Methode parse() verwenden und das formatter-Objekt als Parameter übergeben, damit Java genau weiß, welches Zeitformat wir benötigen;
  3. Als nächstes konvertiert die Methode atStartOfDay(ZoneId.systemDefault()) LocalDate zu ZonedDateTime zu Beginn des Tages in der Standardzeitzone des Systems. Dies ist notwendig, da LocalDate keine Zeitinformationen enthält. Die Methode toInstant() konvertiert ZonedDateTime zu Instant. Date.from(Instant) wird verwendet, um ein Date-Objekt von Instant zu erhalten.

Jetzt müssen wir die Methode ändern, damit sie einen String als Parameter akzeptiert, was es uns bequemer macht, damit zu arbeiten.

Zuerst müssen wir den Datentyp der Parameter in der Schnittstellenklasse ändern und dann mit der Bearbeitung der Implementierung fortfahren:

So sieht unser endgültiger Code aus. Wie Sie sehen können, haben wir eine private Methode verwendet, um das Datum vom String-Format in das Format der Date-Objektklasse umzuwandeln.

Um diese Methode zu verwenden, müssen wir das Datum jetzt nur noch im Format "yyyy-MM-dd" angeben. Lassen Sie uns die Funktionalität dieser Methoden in der main-Methode überprüfen, um sicherzustellen, dass alles korrekt funktioniert:

1. Welche Methode wird verwendet, um eine SQL-Abfrage in Hibernate zu erstellen?

2. Wie spezifiziert man Parameter in einer HQL-Abfrage?

3. Welches Merkmal unterscheidet HQL von SQL?

4. Wie verbessert die Verwendung der LocalDate-Klasse für Datumsparameter in Abfragen den Code?

Welche Methode wird verwendet, um eine SQL-Abfrage in Hibernate zu erstellen?

Welche Methode wird verwendet, um eine SQL-Abfrage in Hibernate zu erstellen?

Wählen Sie die richtige Antwort aus

Wie spezifiziert man Parameter in einer HQL-Abfrage?

Wie spezifiziert man Parameter in einer HQL-Abfrage?

Wählen Sie die richtige Antwort aus

Welches Merkmal unterscheidet HQL von SQL?

Welches Merkmal unterscheidet HQL von SQL?

Wählen Sie die richtige Antwort aus

Wie verbessert die Verwendung der `LocalDate`-Klasse für Datumsparameter in Abfragen den Code?

Wie verbessert die Verwendung der LocalDate-Klasse für Datumsparameter in Abfragen den Code?

Wählen Sie die richtige Antwort aus

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 2. Kapitel 7
We're sorry to hear that something went wrong. What happened?
some-alt