Beispiele für Strategien zum Abrufen des Ruhezustands
Hibernate hat nur wenige Abrufstrategien, um die von Hibernate generierte select-Anweisung so zu optimieren, dass sie so effizient wie möglich ist. Die Abrufstrategie wird in der Zuordnungsbeziehung deklariert, um zu definieren, wie Hibernate die zugehörigen Sammlungen und Entitäten abruft.
Abrufen von Strategien
Es gibt vier Abrufstrategien
1. fetch- “join” = Deaktiviere das verzögerte Laden, lade immer alle Sammlungen und Entitäten.
2. fetch- “select” (Standard) = Lazy lädt alle Sammlungen und Entitäten.
3. Batch-Größe = "N" = Abrufen von bis zu "N" Sammlungen oder Entitäten,Not record.
4. fetch- “subselect” = Gruppiert seine Sammlung in eine Sub Select-Anweisung.
Für eine detaillierte Erklärung können Sie dieHibernate documentation überprüfen.
Beispiele für das Abrufen von Strategien
Hier ist ein Beispiel für eine Eins-zu-Viele-Beziehung für die Demonstration der Abrufstrategien. Ein Bestand ist Bestandteil vieler aktientäglicher Aufzeichnungen.
Beispiel zum Deklarieren von Abrufstrategien in einer XML-Datei
...
Beispiel zum Deklarieren von Abrufstrategien in Annotationen
... @Entity @Table(name = "stock", catalog = "example") public class Stock implements Serializable{ ... @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock") @Cascade(CascadeType.ALL) @Fetch(FetchMode.SELECT) @BatchSize(size = 10) public SetgetStockDailyRecords() { return this.stockDailyRecords; } ... }
Lassen Sie uns untersuchen, wie sich Abrufstrategien auf die im Ruhezustand generierte SQL-Anweisung auswirken.
1. fetch = ”select” oder @Fetch (FetchMode.SELECT)
Dies ist die Standardabrufstrategie. Es ermöglichte das verzögerte Laden aller zugehörigen Sammlungen. Schauen wir uns das Beispiel an ...
//call select from stock Stock stock = (Stock)session.get(Stock.class, 114); Set sets = stock.getStockDailyRecords(); //call select from stock_daily_record for ( Iterator iter = sets.iterator();iter.hasNext(); ) { StockDailyRecord sdr = (StockDailyRecord) iter.next(); System.out.println(sdr.getDailyRecordId()); System.out.println(sdr.getDate()); }
Ausgabe
Hibernate: select ...from example.stock where stock0_.STOCK_ID=? Hibernate: select ...from example.stock_daily_record where stockdaily0_.STOCK_ID=?
Hibernate hat zwei select-Anweisungen generiert
1. Wählen Sie eine Anweisung aus, um die Bestandsdatensätze abzurufen -session.get(Stock.class, 114)
2. Wählen Sie die zugehörigen Sammlungen aus -sets.iterator()
2. fetch = ”join” oder @Fetch (FetchMode.JOIN)
Die Abrufstrategie "Verbinden" deaktiviert das verzögerte Laden aller zugehörigen Sammlungen. Schauen wir uns das Beispiel an ...
//call select from stock and stock_daily_record Stock stock = (Stock)session.get(Stock.class, 114); Set sets = stock.getStockDailyRecords(); //no extra select for ( Iterator iter = sets.iterator();iter.hasNext(); ) { StockDailyRecord sdr = (StockDailyRecord) iter.next(); System.out.println(sdr.getDailyRecordId()); System.out.println(sdr.getDate()); }
Ausgabe
Hibernate: select ... from example.stock stock0_ left outer join example.stock_daily_record stockdaily1_ on stock0_.STOCK_ID=stockdaily1_.STOCK_ID where stock0_.STOCK_ID=?
Hibernate hat nur eine select-Anweisung generiert und ruft alle zugehörigen Sammlungen ab, wenn der Bestand initialisiert wird. -session.get(Stock.class, 114)
1. Wählen Sie die Anweisung aus, um die Bestandsdatensätze abzurufen und den zugehörigen Sammlungen beizutreten.
3. Batch-Größe = "10" oder @BatchSize (Größe = 10)
Diese Strategie zum Abrufen der Stapelgröße wird von vielen Hibernate-Entwicklern immer wieder missverstanden. Sehen wir uns hier das Konzept vonmisunderstandan…
Stock stock = (Stock)session.get(Stock.class, 114); Set sets = stock.getStockDailyRecords(); for ( Iterator iter = sets.iterator();iter.hasNext(); ) { StockDailyRecord sdr = (StockDailyRecord) iter.next(); System.out.println(sdr.getDailyRecordId()); System.out.println(sdr.getDate()); }
Was ist Ihr erwartetes Ergebnis, sind dies 10 Datensätze pro Abruf aus der Sammlung? Siehe die Ausgabe
Output
Hibernate: select ...from example.stock where stock0_.STOCK_ID=? Hibernate: select ...from example.stock_daily_record where stockdaily0_.STOCK_ID=?
Die Batch-Größe hat hier nichts bewirkt, es ist nicht so, wie die Batch-Größe funktioniert. Siehe diese Aussage.
Die Strategie zum Abrufen der Stapelgröße definiert nicht, wie viele Datensätze in den Auflistungen geladen werden. Stattdessen wird festgelegt, wie viele Sammlungen geladen werden sollen.
- Wiederhole N-mal, bis du dich an diese Aussage erinnerst -
Ein anderes Beispiel
Sehen Sie sich ein weiteres Beispiel an, in dem Sie alle Bestandsaufzeichnungen und die zugehörigen täglichen Bestandsaufzeichnungen (Sammlungen) nacheinander ausdrucken möchten.
Listlist = session.createQuery("from Stock").list(); for(Stock stock : list){ Set sets = stock.getStockDailyRecords(); for ( Iterator iter = sets.iterator();iter.hasNext(); ) { StockDailyRecord sdr = (StockDailyRecord) iter.next(); System.out.println(sdr.getDailyRecordId()); System.out.println(sdr.getDate()); } }
Keine Strategie zum Abrufen der Stapelgröße
Ausgabe
Hibernate: select ... from example.stock stock0_ Hibernate: select ... from example.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID=? Hibernate: select ... from example.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID=? Keep repeat the select statements....depend how many stock records in your table.
Wenn Sie 20 Bestandsdatensätze in der Datenbank haben, werden mit den Standardabrufstrategien des Ruhezustands 20 + 1 Auswahlanweisungen generiert und die Datenbank erreicht.
1. Wählen Sie eine Anweisung aus, um alle Bestandsdatensätze abzurufen.
2. Wählen Sie die zugehörige Sammlung
3 aus. Wählen Sie die zugehörige Sammlung
aus. 4. Wählen Sie die zugehörige Sammlung
….
21 aus. Wählen Sie die zugehörige Sammlung aus
Die generierten Abfragen sind nicht effizient und verursachen schwerwiegende Leistungsprobleme.
Die Abrufstrategie "Batch-Size = 10" wurde aktiviert
Ein weiteres Beispiel mit aktivierter Stapelgröße = "10" ist aktiviert.
Output
Hibernate: select ... from example.stock stock0_ Hibernate: select ... from example.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID in ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
Jetzt ruft Hibernate die Sammlungen mit einer ausgewähltenin-Anweisung ab. Wenn Sie über 20 Bestandsaufzeichnungen verfügen, werden 3 ausgewählte Anweisungen generiert.
1. Wählen Sie eine Anweisung aus, um alle Bestandsdatensätze abzurufen.
2. Wählen Sie In-Anweisung, um die zugehörigen Sammlungen abzurufen (10 Sammlungen gleichzeitig)
3. Wählen Sie In Anweisung, um die zugehörigen Sammlungen per-Fetch (jeweils die nächsten 10 Sammlungen) abzurufen.
Bei aktivierter Stapelgröße werden die SELECT-Anweisungen von 21 SELECT-Anweisungen auf 3 SELECT-Anweisungen vereinfacht.
4. fetch = ”subselect” oder @Fetch (FetchMode.SUBSELECT)
Diese Abrufstrategie aktiviert die gesamte zugehörige Sammlung in einer Sub-Select-Anweisung. Lassen Sie die gleiche Abfrage noch einmal sehen ..
Listlist = session.createQuery("from Stock").list(); for(Stock stock : list){ Set sets = stock.getStockDailyRecords(); for ( Iterator iter = sets.iterator();iter.hasNext(); ) { StockDailyRecord sdr = (StockDailyRecord) iter.next(); System.out.println(sdr.getDailyRecordId()); System.out.println(sdr.getDate()); } }
Ausgabe
Hibernate: select ... from example.stock stock0_ Hibernate: select ... from example.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID in ( select stock0_.STOCK_ID from example.stock stock0_ )
Bei aktivierter Unterauswahl werden zwei select-Anweisungen erstellt.
1. Wählen Sie eine Anweisung aus, um alle Bestandsdatensätze abzurufen.
2. Wählen Sie alle zugehörigen Sammlungen in einer Unterauswahlabfrage aus.
Fazit
Die Abrufstrategien sind hochflexibel und ein sehr wichtiger Schritt zur Optimierung der Ruhezustandsabfrage. Wenn Sie sie jedoch an einer falschen Stelle verwenden, ist dies eine Katastrophe.