Zuordnen einer Ruhezustandsabfrage zu einer benutzerdefinierten Klasse

1. Überblick

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

In diesem kurzen Lernprogramm erfahren Sie, wie wir dies mithilfe einer benutzerdefinierten Klasse in Hibernate erreichen können.

2. Die Wesen

Lassen Sie uns zunächst die Entitäten betrachten, die wir zum Abrufen der Daten 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;

   //constructor, getters and setters
}

@Entity
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String name;

    @OneToMany(mappedBy="department")
    private List<DeptEmployee> employees;

    public Department(String name) {
        this.name = name;
    }

   //getters and setters
}

Hier haben wir zwei Entitäten - DeptEmployee und Department . Nehmen wir zur Vereinfachung an, dass ein DeptEmployee nur zu einer Department gehören kann .

Ein Department kann jedoch mehrere DeptEmployees haben.

3. Eine benutzerdefinierte Abfrageergebnisklasse

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

Normalerweise würden wir diese Daten mit einer Abfrage wie folgt abrufen:

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

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

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

Sie können nur die Informationen abrufen, die wir benötigen, indem Sie die Eigenschaften in der select-Klausel angeben.

Wenn wir dies tun, gibt Hibernate jedoch eine Liste von Arrays statt einer Liste von Objects 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. Aber zum Glück können wir Hibernate dazu bringen, diese Daten in eine Klasse einzugeben.

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 ist, sondern nur ein POJO. Wir können jedoch auch eine Entität verwenden, solange sie einen Konstruktor hat, der alle Attribute übernimmt, die wir als Parameter auffüllen möchten.

Im nächsten Abschnitt wird erläutert, warum der Konstruktor wichtig ist.

4. Verwenden eines Konstruktors in HQL

Schauen wir uns nun den HQL an, der diese Klasse verwendet:

Query<Result> query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name)"
  + " from com.baeldung.hibernate.entities.DeptEmployee m");
List<Result> 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. Dies gibt eine Liste von Result_ -Objekten mit den Daten aus den Spalten zurück.

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

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

5. Verwendung 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<Result> results = query.list();
Result result = results.get(0);
assertEquals("John Smith", result.getEmployeeName());
assertEquals("Sales", result.getDepartmentName());

Wir verwenden die Methode __Transformers.aliasToBean () , um die abgerufenen Daten zu verwenden, um die Objekte Result __objects aufzufüllen.

Daher müssen wir sicherstellen, dass die Spaltennamen oder deren Aliase in der select-Anweisung mit den Eigenschaften der _Result _ -Klasse übereinstimmen.

Beachten Sie, dass https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/Query.html#setResTransformer-org.hibernate.transform.ResultTransformer- [ _Query.setResultTransformer( ResultTransformer( ResultTransformerd _ ) nicht mehr unterstützt wurde seit dem Winterschlaf 5.2.

6. Fazit

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

Der Quellcode, der diesem Artikel beiliegt, ist verfügbar unter über GitHub .