Benannte Abfrage im Ruhezustand

1. Übersicht

Ein Hauptnachteil der Verteilung von HQL und SQL auf Datenzugriffsobjekte besteht darin, dass der Code nicht mehr lesbar ist. Daher kann es sinnvoll sein, alle HQL- und SQL-Dateien an einem Ort zu gruppieren und nur ihre Referenz im eigentlichen Datenzugriffscode zu verwenden. Glücklicherweise können wir im Ruhezustand dies mit benannten Abfragen tun.

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 Annotationen @NamedQuery und @NamedNativeQuery definieren 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 Annotation org.hibernate.annotations.NamedQuery . Es erweitert die javax .persistence.NamedQuery um Hibernate-Funktionen.

Wir definieren es als Annotation der DeptEmployee- Klasse:

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

Es ist wichtig zu beachten, dass jede @ NamitedQuery- Annotation genau einer Entitätsklasse oder zugeordneten Superklasse zugeordnet ist. Da der Umfang der benannten Abfragen jedoch die gesamte Persistenzeinheit ist, sollten wir den Abfragenamen sorgfältig auswählen, um eine Kollision zu vermeiden. Dies haben wir 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 Operation im DML-Stil sein kann. Es muss also nicht nur eine select- Anweisung sein. Beispielsweise können wir eine Aktualisierungsabfrage wie in DeptEmployee_UpdateEmployeeDesignation oben haben.

3.1. Abfragefunktionen konfigurieren

Mit der Annotation @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 festlegen wie:

  • zwischenspeicherbar - ob die Abfrage (Ergebnisse) zwischengespeichert werden kann oder nicht
  • cacheMode - der für diese Abfrage verwendete Cache-Modus; Dies kann GET, IGNORE, NORMAL, PUT oder REFRESH sein
  • cacheRegion - Wenn die Abfrageergebnisse zwischengespeichert werden können, benennen Sie den zu verwendenden Abfrage-Cache-Bereich
  • Kommentar - Ein Kommentar, der der generierten SQL-Abfrage hinzugefügt wurde. Zielgruppe sind DBAs
  • flushMode - Der Flush-Modus für diese Abfrage, IMMER AUTO, COMMIT, MANUAL oder PERSISTENCE_CONTEXT

3.2. Verwenden der benannten Abfrage

Nachdem wir die benannte Abfrage definiert haben, verwenden wir sie, um einen Mitarbeiter abzurufen:

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

Hier haben wir die Methode createNamedQuery verwendet. Es nimmt den Namen der Abfrage an und gibt ein org.hibernate.query.Query- Objekt zurück.

4. Benannte native Abfrage

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

Lassen Sie uns diese Anmerkung anhand eines Beispiels untersuchen:

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

Da dies eine native Abfrage ist, müssen wir Hibernate mitteilen, welcher Entitätsklasse die Ergebnisse zugeordnet werden sollen. Aus diesem Grund haben wir hierfür die Eigenschaft resultClass verwendet .

Eine andere Möglichkeit, die Ergebnisse zuzuordnen, besteht in der Verwendung der Eigenschaft resultSetMapping . Hier können wir den Namen eines vordefinierten SQLResultSetMapping angeben .

Beachten Sie, dass wir nur resultClass und resultSetMapping verwenden können .

4.1. Verwenden der benannten nativen Abfrage

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

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

Oder die Session.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 eine NativeQuery zurück, die eine Unterklasse von Query ist .

5. Gespeicherte Prozeduren und Funktionen

Wir können die Annotation @NamedNativeQuery verwenden , 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 dies eine Aktualisierungsabfrage ist, die resultClass- Eigenschaft verwendet haben. Dies liegt daran, dass Hibernate keine reinen nativen Skalarabfragen unterstützt. Um das Problem zu umgehen , müssen Sie entweder eine resultClass oder eine resultSetMapping festlegen.

6. Fazit

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

Der Quellcode ist auf GitHub verfügbar.