Carregamento lento

Disponível

1.1 Antecedentes do problema

Ao começar a trabalhar com bancos de dados reais, você se lembrará imediatamente da frase “A otimização prematura é a raiz de todos os males”. Só agora você se lembra dela de uma forma negativa. Ao trabalhar com um banco de dados, a otimização é indispensável. E você precisa trabalhar com isso já na fase de design.

O Hibernate torna o trabalho com o banco de dados muito conveniente. Você pode obter facilmente qualquer objeto filho apenas anotando @OneToManye @ManyToMany. Exemplo:

@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 como é fácil obter os comentários do usuário:

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

E você terá uma grande surpresa. O usuário tem vários milhares de comentários. Se você escrever um código como este, o Hibernate certamente carregará todos os comentários do usuário. Mas será muito lento, os comentários ocuparão muita memória e assim por diante.

É por isso que você não pode escrever assim! Em teoria sim, mas na prática não.

1.2 Piorando as coisas com as coleções

O problema é ainda mais interessante. Afinal, geralmente você nunca precisa de todos os comentários do usuário. Mesmo que você os exiba em algum lugar do cliente, prefira fazê-lo em partes - páginas.

Então você precisa de métodos como este:

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);
   }

}

O primeiro método retorna apenas uma página de comentários - 50 peças. O segundo método retorna o número de páginas de comentários. E isso é o pior. Para simplesmente descobrir o número de comentários, você tinha que baixar todos os comentários do banco de dados!

1.3 Luz no fim do túnel

Portanto, ninguém usa nossas maravilhosas coleções infantis. Não, claro que são usados, mas apenas como parte de consultas HQL. Por exemplo assim:

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);
     }

}

A boa notícia é que podemos implementar nossos métodos de forma que não precisemos carregar dados extras do banco de dados. A má notícia é que não é fácil trabalhar com nossas coleções.

Comentários
  • Populares
  • Novas
  • Antigas
Você precisa acessar para deixar um comentário
Esta página ainda não tem nenhum comentário