3.1 Einführung

Eine weitere nützliche Sache, über die ich sprechen möchte, ist NativeQuery . Wie Sie bereits wissen, können Sie mit NativeQuery Abfragen in nativem SQL schreiben. Noch interessanter ist jedoch, dass Sie beim Abrufen des Abfrageergebnisses keine Klassenzuordnung verwenden müssen.

Ich zeige Ihnen lieber ein Beispiel:

List<Object[]> persons = session.createNativeQuery("SELECT * FROM Person").list();

In diesem Beispiel übergeben wir keine Klasse, die mit den Abfrageergebniszeilen übereinstimmt, sondern verwenden einfach ein Array von Object-Objekten.

Dies kann nützlich sein, wenn Sie nur ein paar Spalten in einer Tabelle auswählen möchten. Beispiel:


List<Object[]> persons = session.createNativeQuery("SELECT id, name FROM Person").list();
 
for(Object[] person : persons) {
    Number id = (Number) person[0];
    String name = (String) person[1];
}

Dies ähnelt in gewisser Weise dem JDBC-Ansatz, bei dem Sie ein ResultSet-Objekt abrufen und Daten aus seinen Zeilen lesen.

Hibernate bietet jedoch verschiedene Möglichkeiten, dies zuverlässiger zu machen. Sie können beispielsweise den Typ der Spalten angeben, die Sie subtrahieren möchten. Beispiel:


Query<Object[]> query = session.createNativeQuery("SELECT id, name FROM Person");
query.addScalar("id", StandardBasicTypes.LONG);
query.addScalar("name", StandardBasicTypes.STRING);
List<Object[]> persons = query.list();
 
for(Object[] person : persons) {
    Long id = (Long) person[0];
    String name = (String) person[1];
}

3.2 Entitätszuordnung

Sie können auch explizit die Klasse angeben, die Hibernate beim Parsen des Ergebnisses von NativeQuery verwenden soll . Dies kann auf unterschiedliche Weise erfolgen.


Query<Person> query = session.createNativeQuery("SELECT * FROM Person")
    .addEntity(Person.class);
    .list();

Und natürlich das gute alte Format, das Sie kennen:


Query<Person> query = session.createNativeQuery("SELECT * FROM Person", Person.class).list();

Der erste Ansatz ist der native Hibernate-Ansatz und der zweite der JPA-Ansatz. Der JPA-Ansatz ist bequemer und prägnanter, da dieser Standard erfunden wurde, nachdem Hibernate viele Jahre lang existierte. Und Hibernate entwickelte sich weiter und war gezwungen, alte Ansätze zu unterstützen, um die Kompatibilität mit seinen alten Versionen aufrechtzuerhalten.

Dank seines Ansatzes ermöglicht Hibernate übrigens, nicht eine Klasse, sondern mehrere Klassen mit der Abfrageergebniszuordnung zu verbinden. Beispiel:


List<Phone> results = session.createNativeQuery(
    "SELECT {ph.*}, {pr.*}" +
    "FROM Phone ph" +
    "JOIN Person pr ON ph.person_id = pr.id")
.addEntity("ph", Phone.class)
.addJoin("pr", "ph.person")
.list();
 
for (Phone. phone : results) {
           	assertNotNull( phone.getPerson().getName() );
}

Dieser Ansatz mit NativeQuery kann verwendet werden, um die Auswahl von Daten aus der Datenbank zu beschleunigen. Wenn Sie wissen, dass Sie einige Spalten nicht benötigen, können Sie diese in der Anfrage weglassen.

Sie können auch alle untergeordneten Entitäten auf einmal laden, selbst wenn Hibernate Cache oder den LazyLoading -Mechanismus verwenden möchte . Darüber hinaus verfügen Ihre untergeordneten Entitäten möglicherweise über viele Spalten in der Datenbank, von denen Sie nur einige auswählen können.

3.3 DTO-Zuordnung

Hibernate ermöglicht Ihnen auch die Verwendung von Nicht-Entity-Klassen zum Zuordnen des Ergebnisses. Klassen, die keine Anmerkungen haben und keiner Tabelle zugeordnet sind.

Beispiel:

public class PersonSummaryDTO {
    private Number id;
    private String name;

    public Number getId() {
    	return id;
    }

    public void setId(Number id) {
    	this.id = id;
    }

    public String getName() {
    	return name;
    }

    public void setName(String name) {
    	this.name = name;
	}
}

List<PersonSummaryDTO> dtos = session.createNativeQuery(
    "SELECT p.id as \"id\", p.name as \"name\" FROM Person p")
.setResultTransformer(Transformers.aliasToBean(PersonSummaryDTO.class) )
.list();

Da es in der PersonSummaryDTO-Klasse keine Anmerkungen gibt, müssen die Namen der Spalten in der SQL-Abfrage genau mit den Namen der Felder der PersonSummaryDTO-Klasse übereinstimmen.

Dies kann sehr nützlich sein, wenn Sie Daten aus einer externen Datenbank lesen, mit der Ihre Anwendung nur im schreibgeschützten Modus verbunden ist. Das heißt, Sie haben Zugriff auf Tabellen mit mehr als 50 Spalten erhalten. Sie speichern Daten in denormalisierter Form, um die Auswahl zu beschleunigen.

Oder nehmen wir an, jemand hat beschlossen, die Klassenhierarchie in einer Tabelle zu speichern, und in fünf Jahren ist diese Tabelle so stark gewachsen, dass sich der Teufel das Bein brechen wird. Sie müssen einige Spalten aus dieser Tabelle auswählen (ID und Benutzername) und sie dem Client übergeben.

Ich denke, Sie verstehen, aber wenn Sie tiefer in dieses Thema eintauchen möchten, können Sie unter dem Link mehr lesen:

Native SQL-Abfragen