Caricamento pigro

Disponibile

1.1 Contesto del problema

Quando inizi a lavorare con database reali, ricorderai immediatamente la frase "L'ottimizzazione prematura è la radice di tutti i mali". Solo ora la ricordi in modo negativo. Quando si lavora con un database, l'ottimizzazione è indispensabile. E devi lavorarci già in fase di progettazione.

Hibernate rende molto conveniente lavorare con il database. Puoi facilmente ottenere qualsiasi oggetto figlio semplicemente annotando correttamente @OneToManye @ManyToMany. Esempio:

@Entity
@Table(name="user")
class User {
   @Column(name="id")
   public Integer id;

   @OneToMany(cascade = CascadeType.ALL)
   @JoinColumn(name = "user_id")
   public List<Comment> comments;
}

E quanto è facile ottenere i commenti degli utenti:

User user = session.get(User.class, 1);
List<Comment> comments = user.getComments();

E avrai una grande sorpresa. L'utente ha diverse migliaia di commenti. Se scrivi codice come questo, Hibernate ovviamente caricherà tutti i commenti dell'utente. Ma sarà molto lento, i commenti occuperanno molta memoria e così via.

Ecco perché non puoi scrivere così! In teoria sì, ma in pratica no.

1.2 Peggiorare le cose con le collezioni

Il problema è ancora più interessante. Dopotutto, di solito non hai mai bisogno di tutti i commenti dell'utente. Anche se li visualizzi da qualche parte sul client, preferisci farlo in parti: pagine.

Quindi hai bisogno di metodi come questo:

public class CommentsManager {
    private static final PAGE_SIZE = 50;

    public List<Comment> getCommentsPage(int userId, int pageIndex){
     	User user = session.get(User.class, userId);
     	List<Comment> comments = user.getComments();
     	return comments.subList(pageIndex * PAGE_SIZE, PAGE_SIZE);
    }

   public int getCommentsPageCount(int userId)   {
     	User user = session.get(User.class, userId);
     	List<Comment> comments = user.getComments();
     	return Math.ceil(  comments.size()/PAGE_SIZE);
   }

}

Il primo metodo restituisce solo una pagina di commenti: 50 pezzi. Il secondo metodo restituisce il numero di pagine di commenti. E questo è il peggio. Per scoprire semplicemente il numero di commenti, dovevi scaricare tutti i commenti dal database!

1.3 Luce alla fine del tunnel

Pertanto, nessuno usa le nostre meravigliose collezioni per bambini. No, ovviamente vengono utilizzati, ma solo come parte delle query HQL. Ad esempio in questo modo:

public class CommentsManager {
      private static final PAGE_SIZE = 50;

       public List<Comment> getCommentsPage(int userId, int pageIndex){
           	String hql = "select comments from User where id = :id";
           	Query<Comment> query = session.createQuery( hql, Comment.class);
           	query.setParametr("id", userId);
           	query.setOffset(pageIndex * PAGE_SIZE);
           	query.setLimit(PAGE_SIZE);
           	return query.list();
      }

      public int getCommentsPageCount(int userId)   {
           	String hql = "select count(comments) from User where id = :id";
           	Query<Integer> query = session.createQuery( hql, Integer.class);
           	query.setParametr("id", userId);
           	return Math.ceil(query.singleResult()/PAGE_SIZE);
     }

}

La buona notizia è che possiamo implementare i nostri metodi in modo tale da non dover caricare dati aggiuntivi dal database. La cattiva notizia è che non è facile lavorare con le nostre collezioni.

Commenti
  • Popolari
  • Nuovi
  • Vecchi
Devi avere effettuato l'accesso per lasciare un commento
Questa pagina non ha ancora commenti