Zuordnen einer Abfrage im Ruhezustand zu einer benutzerdefinierten Klasse

1. Übersicht

Wenn wir den Ruhezustand verwenden, um Daten aus der Datenbank abzurufen, werden standardmäßig die abgerufenen Daten verwendet, um das gesamte Objektdiagramm für das angeforderte Objekt zu erstellen. Manchmal möchten wir jedoch möglicherweise nur einen Teil der Daten abrufen, vorzugsweise in einer flachen Struktur.

In diesem kurzen Tutorial werden wir sehen, wie wir dies im Ruhezustand mithilfe einer benutzerdefinierten Klasse erreichen können.

2. Die Entitäten

Schauen wir uns zunächst die Entitäten an, mit denen wir die Daten abrufen:

@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; // constructor, getters and setters } @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String name; @OneToMany(mappedBy="department") private List employees; public Department(String name) { this.name = name; } // getters and setters  }

Hier haben wir zwei Entitäten - DeptEmployee und Department . Nehmen wir der Einfachheit halber an, dass ein DeptEmployee nur einer Abteilung angehören kann .

Eine Abteilung kann jedoch mehrere DeptEmployees haben .

3. Eine benutzerdefinierte Abfrageergebnisklasse

Angenommen, wir möchten eine Liste aller Mitarbeiter mit nur ihrem Namen und dem Namen ihrer Abteilung drucken.

Normalerweise rufen wir diese Daten mit einer Abfrage wie der folgenden ab:

Query query = session.createQuery("from com.baeldung.hibernate.entities.DeptEmployee"); List deptEmployees = query.list();

Dadurch werden alle Mitarbeiter, alle ihre Eigenschaften, die zugehörige Abteilung und alle ihre Eigenschaften abgerufen.

In diesem speziellen Fall kann dies jedoch etwas teuer sein, da wir nur den Namen des Mitarbeiters und den Namen der Abteilung benötigen.

Eine Möglichkeit, nur die benötigten Informationen abzurufen, besteht darin, die Eigenschaften in der select-Klausel anzugeben.

Wenn wir dies tun, gibt Hibernate eine Liste von Arrays anstelle einer Liste von Objekten zurück:

Query query = session.createQuery("select m.name, m.department.name from com.baeldung.hibernate.entities.DeptEmployee m"); List managers = query.list(); Object[] manager = (Object[]) managers.get(0); assertEquals("John Smith", manager[0]); assertEquals("Sales", manager[1]);

Wie wir sehen können, ist die Verarbeitung der zurückgegebenen Daten etwas umständlich. Glücklicherweise können wir Hibernate dazu bringen, diese Daten in eine Klasse zu füllen.

Schauen wir uns die Result- Klasse an, mit der wir die abgerufenen Daten füllen:

public class Result { private String employeeName; private String departmentName; public Result(String employeeName, String departmentName) { this.employeeName = employeeName; this.departmentName = departmentName; } public Result() { } // getters and setters }

Beachten Sie, dass die Klasse keine Entität, sondern nur ein POJO ist. Wir können jedoch auch eine Entität verwenden, sofern sie über einen Konstruktor verfügt, der alle Attribute, die wir füllen möchten, als Parameter verwendet.

Wir werden im nächsten Abschnitt sehen, warum der Konstruktor wichtig ist.

4. Verwenden eines Konstruktors in HQL

Schauen wir uns nun die HQL an, die diese Klasse verwendet:

Query query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name)" + " from com.baeldung.hibernate.entities.DeptEmployee m"); List results = query.list(); Result result = results.get(0); assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName());

Hier verwenden wir den Konstruktor, den wir in der Result- Klasse definiert haben, zusammen mit den Eigenschaften, die wir abrufen möchten. Dadurch wird eine Liste der Ergebnisobjekte mit den aus den Spalten ausgefüllten Daten zurückgegeben.

Wie wir sehen können, ist die zurückgegebene Liste einfacher zu verarbeiten als die Verwendung einer Liste von Objektarrays.

Es ist wichtig zu beachten, dass wir den vollständig qualifizierten Namen der Klasse in der Abfrage verwenden müssen.

5. Verwenden eines ResultTransformers

Eine Alternative zur Verwendung eines Konstruktors in der HQL-Abfrage ist die Verwendung eines ResultTransformer:

Query query = session.createQuery("select m.name as employeeName, m.department.name as departmentName" + " from com.baeldung.hibernate.entities.DeptEmployee m"); query.setResultTransformer(Transformers.aliasToBean(Result.class)); List results = query.list(); Result result = results.get(0); assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName());

Wir benutzen die Transformatoren. aliasToBean () -Methode zum Verwenden der abgerufenen Daten zum Auffüllen der Ergebnisobjekte .

Folglich müssen wir sicherstellen, dass die Spaltennamen oder ihre Aliase in der select-Anweisung mit den Eigenschaften der Result- Klasse übereinstimmen .

Beachten Sie, dass Query.setResultTransformer ( ResultTransformer ) seit Hibernate 5.2 veraltet ist.

6. Fazit

In diesem Artikel haben wir gesehen, wie eine benutzerdefinierte Klasse zum Abrufen von Daten in einer leicht lesbaren Form verwendet werden kann.

Der diesem Artikel beiliegende Quellcode ist auf GitHub verfügbar.