Caricamento desideroso / pigro in ibernazione

Persistenza in alto

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO

1. Introduzione

Quando si lavora con un ORM, il recupero / caricamento dei dati può essere classificato in due tipi: desideroso e pigro.

In questo rapido articolo indicheremo le differenze e mostreremo che possono essere utilizzate in Hibernate.

2. Dipendenze di Maven

Per poter utilizzare Hibernate, definiamo prima la dipendenza principale nel nostro pom.xml :

 org.hibernate hibernate-core 5.2.2.Final 

L'ultima versione di Hibernate può essere trovata qui.

3. Caricamento desideroso e pigro

La prima cosa di cui dovremmo discutere qui è cosa sono il caricamento lento e il caricamento desideroso:

  • Eager Loading è un modello di progettazione in cui l'inizializzazione dei dati avviene sul posto
  • Lazy Loading è un modello di progettazione utilizzato per posticipare l'inizializzazione di un oggetto il più a lungo possibile

Vediamo come funziona effettivamente con alcuni esempi:

La classe UserLazy :

@Entity @Table(name = "USER") public class UserLazy implements Serializable { @Id @GeneratedValue @Column(name = "USER_ID") private Long userId; @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") private Set orderDetail = new HashSet(); // standard setters and getters // also override equals and hashcode }

La classe OrderDetail :

@Entity @Table (name = "USER_ORDER") public class OrderDetail implements Serializable { @Id @GeneratedValue @Column(name="ORDER_ID") private Long orderId; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="USER_ID") private UserLazy user; // standard setters and getters // also override equals and hashcode }

Un utente può avere più OrderDetails . Nella strategia di caricamento ansioso, se carichiamo i dati dell'utente , caricherà anche tutti gli ordini ad esso associati e li memorizzerà in una memoria .

Ma, quando il caricamento lazy è abilitato, se richiamiamo un UserLazy , i dati di OrderDetail non verranno inizializzati e caricati in una memoria finché non viene effettuata una chiamata esplicita.

Nella prossima sezione vedremo come l'esempio sopra è implementato in Hibernate.

4. Caricamento della configurazione

In questa sezione vedremo come configurare le strategie di recupero in Hibernate. Riutilizzeremo gli esempi della sezione precedente.

Il caricamento lento può essere abilitato semplicemente utilizzando il seguente parametro di annotazione:

fetch = FetchType.LAZY

Per utilizzare Eager Fetching viene utilizzato il seguente parametro:

fetch = FetchType.EAGER

Per impostare Eager Loading abbiamo usato UserLazy classe doppia 's chiamato UserEager .

Nella prossima sezione esamineremo le differenze tra i due tipi di recupero.

5. Differenze

Come accennato, la principale differenza tra i due tipi di recupero è un momento in cui i dati vengono caricati in una memoria.

Diamo un'occhiata a questo esempio:

List users = sessionLazy.createQuery("From UserLazy").list(); UserLazy userLazyLoaded = users.get(3); return (userLazyLoaded.getOrderDetail());

Con l'approccio di inizializzazione pigra, orderDetailSet verrà inizializzato solo quando viene chiamato esplicitamente utilizzando un getter o un altro metodo come mostrato nell'esempio precedente:

UserLazy userLazyLoaded = users.get(3);

Ma con un approccio entusiasta in UserEager verrà inizializzato immediatamente nella prima riga dell'esempio precedente:

List user = sessionEager.createQuery("From UserEager").list();

Per il caricamento lento viene utilizzato un oggetto proxy e una query SQL separata viene attivata per caricare orderDetailSet .

L'idea di disabilitare i proxy o il caricamento lento è considerata una cattiva pratica in Hibernate. Può comportare il recupero di molti dati da un database e l'archiviazione in una memoria, indipendentemente dalla necessità.

Il seguente metodo può essere utilizzato per testare la funzionalità di cui sopra:

Hibernate.isInitialized(orderDetailSet);

Ora è importante dare un'occhiata alle query che vengono generate in entrambi i casi:

true

L'impostazione precedente in fetching.hbm.xml mostra le query SQL generate. Se guardi un output della console, sarai in grado di vedere le query generate.

Per il caricamento lento, la query generata per caricare i dati dell'utente :

select user0_.USER_ID as USER_ID1_0_, ... from USER user0_

Tuttavia, durante il caricamento impaziente, abbiamo visto un collegamento con USER_ORDER:

select orderdetai0_.USER_ID as USER_ID4_0_0_, orderdetai0_.ORDER_ID as ORDER_ID1_1_0_, orderdetai0_ ... from USER_ORDER orderdetai0_ where orderdetai0_.USER_ID=?

La query precedente viene generata per tutti gli utenti , il che si traduce in un utilizzo di molta più memoria rispetto all'altro approccio.

6. Vantaggi e svantaggi

6.1. Caricamento pigro

Vantaggi:

  • Tempo di caricamento iniziale molto inferiore rispetto all'altro approccio
  • Minor consumo di memoria rispetto all'altro approccio

Disadvantages:

  • Delayed initialization might impact performance during unwanted moments
  • In some cases you need to handle lazily-initialized objects with a special care or you might end up with an exception

6.2. Eager Loading:

Advantages:

  • No delayed initialization related performance impacts

Disadvantages:

  • Long initial loading time
  • Loading too much unnecessary data might impact performance

7. Lazy Loading in Hibernate

Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes.

Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity’s class. In our example, when a requested information is missing, it will be loaded from a database before control is ceded to the User class implementation.

Va inoltre notato che quando l'associazione è rappresentata come una classe di raccolta (negli esempi precedenti è rappresentata come Set orderDetailSet ), viene creato un wrapper che sostituisce una raccolta originale.

Per saperne di più sul modello di progettazione proxy puoi fare riferimento qui.

8. Conclusione

In questo articolo, abbiamo mostrato esempi dei due principali tipi di recupero usati in Hibernate.

Per competenze di livello avanzato, puoi consultare il sito Web ufficiale di Hibernate. Per ottenere il codice discusso in questo articolo, dai un'occhiata a questo repository.

Fondo di persistenza

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO