Benannte Abfrage im Ruhezustand

Benannte Abfrage im Ruhezustand

1. Überblick

Ein Hauptnachteil der Streuung von HQL und SQL auf Datenzugriffsobjekte besteht darin, dass der Code dadurch unlesbar wird. Daher kann es sinnvoll sein, alle HQL- und SQL-Anweisungen an einem Ort zu gruppieren und nur deren Referenz im eigentlichen Datenzugriffscode zu verwenden. Glücklicherweise ermöglicht uns Hibernate dies mit benannten Abfragen.

Eine benannte Abfrage ist eine statisch definierte Abfrage mit einer vordefinierten unveränderlichen Abfragezeichenfolge. Sie werden beim Erstellen der Sitzungsfactory überprüft, sodass die Anwendung im Fehlerfall schnell fehlschlägt.

In diesem Artikel erfahren Sie, wie Sie benannte Abfragen im Ruhezustand mithilfe der Anmerkungen@NamedQuery und@NamedNativeQuerydefinieren und verwenden.

2. Die Entität

Schauen wir uns zunächst die Entität an, die wir in diesem Artikel verwenden werden:

@Entity
public class DeptEmployee {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String employeeNumber;

    private String designation;

    private String name;

    @ManyToOne
    private Department department;

    // getters and setters
}

In unserem Beispiel rufen wir einen Mitarbeiter anhand seiner Mitarbeiternummer ab.

3. Benannte Abfrage

Um dies als benannte Abfrage zu definieren, verwenden wir die Annotationorg.hibernate.annotations.NamedQuery. Es erweitert den Javax.persistence.NamedQuery um Hibernate-Funktionen.

Wir definieren es als Annotation der KlasseDeptEmployee:

@org.hibernate.annotations.NamedQuery(name = "DeptEmployee_findByEmployeeNumber",
  query = "from DeptEmployee where employeeNumber = :employeeNo")

It’s important to note that every @NamedQuery annotation is attached to exactly one entity class or mapped superclass. But,since the scope of named queries is the entire persistence unit, we should select the query name carefully to avoid a collision. Und wir haben dies erreicht, indem wir den Entitätsnamen als Präfix verwendet haben.

Wenn wir mehr als eine benannte Abfrage für eine Entität haben, verwenden wir die Annotation@NamedQueries, um diese zu gruppieren:

@org.hibernate.annotations.NamedQueries({
    @org.hibernate.annotations.NamedQuery(name = "DeptEmployee_FindByEmployeeNumber",
      query = "from DeptEmployee where employeeNumber = :employeeNo"),
    @org.hibernate.annotations.NamedQuery(name = "DeptEmployee_FindAllByDesgination",
      query = "from DeptEmployee where designation = :designation"),
    @org.hibernate.annotations.NamedQuery(name = "DeptEmployee_UpdateEmployeeDepartment",
      query = "Update DeptEmployee set department = :newDepartment where employeeNumber = :employeeNo"),
...
})

Beachten Sie, dass die HQL-Abfrage eine DML-artige Operation sein kann. Es muss also nicht nur eineselect-Anweisung sein. Zum Beispiel können wir eine Aktualisierungsabfrage wie inDeptEmployee_UpdateEmployeeDesignation oben haben.

3.1. Abfragefunktionen konfigurieren

Mit der Sannotation@NamedQuery können verschiedene Abfragefunktionen festgelegt werden. Schauen wir uns ein Beispiel an:

@org.hibernate.annotations.NamedQuery(
  name = "DeptEmployee_FindAllByDepartment",
  query = "from DeptEmployee where department = :department",
  timeout = 1,
  fetchSize = 10
)

Hier haben wir das Timeout-Intervall und die Abrufgröße konfiguriert. Abgesehen von diesen beiden können wir auch Funktionen einstellen wie:

  • cacheable - Gibt an, ob die Abfrage (Ergebnisse) zwischengespeichert werden kann oder nicht

  • cacheMode - der für diese Abfrage verwendete Cache-Modus; Dies kann einer vonGET, IGNORE, NORMAL, PUT, oderREFRESH sein

  • cacheRegion - Wenn die Abfrageergebnisse zwischengespeichert werden können, benennen Sie den zu verwendenden Abfrage-Cache-Bereich

  • comment - ein Kommentar, der der generierten SQL-Abfrage hinzugefügt wurde; Zielgruppe sind DBAs

  • flushMode - Der Flush-Modus für diese Abfrage, einer vonALWAYS, AUTO, COMMIT, MANUAL, oderPERSISTENCE_CONTEXT

3.2. Verwenden der benannten Abfrage

Nachdem wir die benannte Abfrage definiert haben, können Sie damit einen Mitarbeiter abrufen:

Query query = session.createNamedQuery("DeptEmployee_FindByEmployeeNumber",
  DeptEmployee.class);
query.setParameter("employeeNo", "001");
DeptEmployee result = query.getSingleResult();

Hier haben wir diecreateNamedQuery-Methode verwendet. Es nimmt den Namen der Abfrage an und gibt einorg.hibernate.query.Query -Objekt zurück.

4. Benannte native Abfrage

Neben HQL-Abfragen können wir auch native SQL als benannte Abfrage definieren. Dazu können wir die Annotation@NamedNativeQueryverwenden. Obwohl es den@NamedQuery ähnlich ist, erfordert es etwas mehr Konfiguration.

Lassen Sie uns diese Annotation anhand eines Beispiels erkunden:

@org.hibernate.annotations.NamedNativeQueries(
    @org.hibernate.annotations.NamedNativeQuery(name = "DeptEmployee_GetEmployeeByName",
      query = "select * from deptemployee emp where name=:name",
      resultClass = DeptEmployee.class)
)

Da es sich um eine native Abfrage handelt, müssen wir Hibernate mitteilen, welcher Entitätsklasse die Ergebnisse zugeordnet werden sollen. Aus diesem Grund haben wir hierfür dieresultClass -Eigenschaft verwendet.

Eine andere Möglichkeit, die Ergebnisse abzubilden, besteht darin, dieresultSetMapping -Eigenschaft zu verwenden. Hier können wir den Namen eines vordefiniertenSQLResultSetMapping angeben.

Beachten Sie, dass wir nur eines vonresultClass undresultSetMapping verwenden können.

4.1. Verwenden der benannten nativen Abfrage

Um die benannte native Abfrage zu verwenden, können wirSession.createNamedQuery() verwenden:

Query query = session.createNamedQuery("DeptEmployee_FindByEmployeeName", DeptEmployee.class);
query.setParameter("name", "John Wayne");
DeptEmployee result = query.getSingleResult();

Oder dieSession.getNamedNativeQuery():

NativeQuery query = session.getNamedNativeQuery("DeptEmployee_FindByEmployeeName");
query.setParameter("name", "John Wayne");
DeptEmployee result = (DeptEmployee) query.getSingleResult();

Der einzige Unterschied zwischen diesen beiden Ansätzen ist der Rückgabetyp. Der zweite Ansatz gibt einNativeQuery, zurück, das eine Unterklasse vonQuery ist.

5. Gespeicherte Prozeduren und Funktionen

Wir können die Annotation@NamedNativeQueryverwenden, um Aufrufe an gespeicherte Prozeduren und Funktionen zu definieren:

@org.hibernate.annotations.NamedNativeQuery(
  name = "DeptEmployee_UpdateEmployeeDesignation",
  query = "call UPDATE_EMPLOYEE_DESIGNATION(:employeeNumber, :newDesignation)",
  resultClass = DeptEmployee.class)

Beachten Sie, dass wir, obwohl es sich um eine Aktualisierungsabfrage handelt, dieresultClass -Eigenschaft verwendet haben. Dies liegt daran, dass Hibernate keine reinen nativen Skalarabfragen unterstützt. Um das Problem zu umgehen, müssen Sie entwederresultClass oderresultSetMapping. festlegen

6. Fazit

In diesem Artikel haben wir gesehen, wie benannte HQL- und native Abfragen definiert und verwendet werden.

Der Quellcode istover on GitHub verfügbar.