Proxy in der Methode Hibernate load ()

1. Übersicht

In diesem Tutorial sehen wir, was ein Proxy im Kontext der load () -Methode von Hibernate ist .

Für Leser, die noch nicht mit Hibernate vertraut sind, sollten Sie sich zunächst mit den Grundlagen vertraut machen.

2. Eine kurze Einführung in Proxies und Last () Methode

Per Definition ist ein Bevollmächtigter „eine Funktion, die befugt ist, als Stellvertreter oder Ersatz für einen anderen zu fungieren“ .

Dies gilt für den Ruhezustand, wenn wir Session.load () aufrufen , um einen so genannten nicht initialisierten Proxy unserer gewünschten Entitätsklasse zu erstellen .

Einfach ausgedrückt, Hibernate unterteilt unsere Entitätsklasse mithilfe der CGLib- Bibliothek in Unterklassen . Abgesehen von der @ ID- Methode delegiert die Proxy-Implementierung alle anderen Eigenschaftsmethoden an die Hibernate-Sitzung, um die Instanz zu füllen.

public class HibernateProxy extends MyEntity {     private MyEntity target;     public String getFirstName() {         if (target == null) {             target = readFromDatabase();         }         return target.getFirstName();     } }

Diese Unterklasse wird zurückgegeben, anstatt die Datenbank direkt abzufragen.

Sobald eine der Entitätsmethoden aufgerufen wird, wird die Entität geladen und zu diesem Zeitpunkt zu einem initialisierten Proxy.

3. Proxies und Lazy Loading

3.1. Eine einzelne Einheit

Denken wir an den Mitarbeiter als Ganzes. Zunächst nehmen wir an, dass es keine Beziehung zu anderen Tabellen hat.

Wenn wir Session.load () verwenden , um einen Mitarbeiter zu instanziieren :

Employee albert = session.load(Employee.class, new Long(1));

Anschließend erstellt Hibernate einen nicht initialisierten Proxy des Mitarbeiters . Es enthält die ID, die wir ihm gegeben haben, hat aber ansonsten keine anderen Werte, da wir die Datenbank noch nicht erreicht haben.

Sobald wir jedoch eine Methode für albert aufrufen :

String firstName = albert.getFirstName();

Anschließend fragt Hibernate die Mitarbeiterdatenbanktabelle nach einer Entität mit dem Primärschlüssel 1 ab und füllt Albert mit seinen Eigenschaften aus der entsprechenden Zeile.

Wenn keine Zeile gefunden wird, löst Hibernate eine ObjectNotFoundException aus .

3.2. Eins-zu-viele-Beziehungen

Erstellen wir nun auch eine Unternehmenseinheit , in der ein Unternehmen viele Mitarbeiter hat:

public class Company {     private String name;     private Set employees; }

Wenn wir diesmal Session.load () für das Unternehmen verwenden:

Company bizco = session.load(Company.class, new Long(1)); String name = bizco.getName();

Dann werden die Eigenschaften des Unternehmens wie zuvor bevölkert, außer dass die Anzahl der Mitarbeiter nur ein bisschen anders ist.

Wir haben nur die Unternehmenszeile abgefragt, aber der Proxy lässt den Mitarbeiter in Ruhe, bis wir getEmployees aufrufen, abhängig von der Abrufstrategie .

3.3. Viele-zu-Eins-Beziehungen

Der Fall ist in umgekehrter Richtung ähnlich:

public class Employee {     private String firstName;     private Company workplace; }

Wenn wir load () erneut verwenden:

Employee bob = session.load(Employee.class, new Long(2)); String firstName = bob.getFirstName();

bob wird nun initialisiert, und der Arbeitsplatz wird nun abhängig von der Abrufstrategie als nicht initialisierter Proxy festgelegt.

4. Faul laden

Jetzt gibt load () uns nicht immer einen nicht initialisierten Proxy. Tatsächlich erinnert uns das Session- Java-Dokument (Hervorhebung hinzugefügt):

Diese Methode gibt möglicherweise eine Proxy-Instanz zurück, die bei Bedarf initialisiert wird, wenn auf eine Methode ohne Kennung zugegriffen wird.

Ein einfaches Beispiel dafür, wann dies passieren kann, ist die Stapelgröße.

Angenommen , wir verwenden @BatchSize für unsere Mitarbeiterentität :

@Entity @BatchSize(size=5) class Employee { // ... }

Und diesmal haben wir drei Mitarbeiter:

Employee catherine = session.load(Employee.class, new Long(3)); Employee darrell = session.load(Employee.class, new Long(4)); Employee emma = session.load(Employee.class, new Long(5));

Wenn wir getFirstName auf catherine aufrufen :

String cathy = catherine.getFirstName();

Dann kann Hibernate tatsächlich entscheiden, alle drei Mitarbeiter gleichzeitig zu laden und alle drei in initialisierte Proxys umzuwandeln.

Und dann, wenn wir nach Darrells Vornamen rufen :

String darrell = darrell.getFirstName();

Dann trifft Hibernate die Datenbank überhaupt nicht.

5. Eifriges Laden

5.1. Mit get ()

Wir können Proxys auch vollständig umgehen und Hibernate bitten, die reale Sache mit Session.get () zu laden :

Employee finnigan = session.get(Employee.class, new Long(6));

Dadurch wird die Datenbank sofort aufgerufen, anstatt einen Proxy zurückzugeben.

Und tatsächlich, statt eines ObjectNotFoundException , wird es zurückgeben null , wenn finnigan existiert nicht.

5.2. Auswirkungen auf die Leistung

Während get () praktisch ist, kann load () die Datenbank leichter machen.

Nehmen wir zum Beispiel an, Gerald wird für ein neues Unternehmen arbeiten:

Employee gerald = session.get(Employee.class, new Long(7)); Company worldco = (Company) session.load(Company.class, new Long(2)); employee.setCompany(worldco); session.save(employee);

Da wir wissen, dass wir in dieser Situation nur den Mitarbeiterdatensatz ändern werden , ist es sinnvoll , load () für das Unternehmen aufzurufen .

Wenn wir get () on Company aufgerufen hätten, hätten wir alle Daten unnötig aus der Datenbank geladen.

6. Fazit

In diesem Artikel haben wir kurz gelernt , wie Hibernate Proxies arbeiten und wie diese Auswirkungen die Belastung Methode mit Entitäten und deren Beziehungen.

Außerdem haben wir uns kurz angesehen, wie sich load () von get () unterscheidet.

Wie üblich ist der vollständige Quellcode, der dem Tutorial beiliegt, auf GitHub verfügbar.