Esse post sobre
paginação com hibernate, considero que você já tenha seu DAO, ManagedBean, o
Bean e a página XHTML feita, e quer apenas mudar a forma como os dados são
trazidos do banco, melhorando dessa forma o desempenho do sistema.
Para
fazermos paginação com o Hibernate, precisamos preparar a camada View (Páginas XHTML) para lidar com
essa paginação. No caso do primefaces, isso é bem simples. Vamos analisar como
fica o componente <p:dataTable> de
forma a trabalhar com a paginação:
<p:dataTable id="carroTable"
paginator="true" rows="20" lazy="true" paginatorAlwaysVisible="false"
paginatorPosition="bottom" var="carro"
value="#{pesquisaCarroBean.lazyCarros}" rowsPerPageTemplate="10,20,50"
emptyMessage="Nenhum carro encontrado." style="margin-top: 20px" >
...
<p:dataTable>
A propriedade paginator=”true”
indica que haverá um paginação, e mesmo que não fizéssemos a parte de paginação
na camada Model, o primefaces conseguiria paginar os dados trazidos para esse
dataTable, porém, mesmo a exibição
estando paginada, todos os dados
estariam carregados em memória. Daí a importância de fazermos realmente a
paginação dos dados, mudando a forma como esses dados são trazidos do banco de
dados, que é o que vamos ver mais a frente nesse post.
A propriedade paginatorAlwaysVisible=”false”
serve para que o paginador aparece apenas quando houver dados suficientes para
serem paginados. O paginatorPosition=”bottom”
informa a posição que a paginação será exibida. A propriedade rows=”20” indica quantas linhas serão
exibidas por default, já a propriedade rowsPerPageTemplate=”10,20,50”
é responsável por permitir a customização da quantidade de linhas
visualizadas.
Porém, a propriedade lazy=”true”
é quem realmente faz o componente do primefaces entender que haverá uma
paginação real dos dados. Com isso, podemos passar para a camada Model.
Precisamos criar uma classe responsável por fazer o meio de
campo entre o componente do primefaces
que será paginado e o método responsável por buscar a consulta paginada usando
o hibernate. Vamos começar criando a
classe LazyCarro, que criei dentro
de um novo pacote chamado lazy_model dentro
da minha hierarquia de pacotes. Segue o código:
public class LazyCarro extends LazyDataModel<Carro> implements Serializable{
private static final long serialVersionUID = 1L;
private CarroDAO carroDAO;
public LazyCarro(CarroDAO carroDAO) {
this.carroDAO =
carroDAO;
}
@Override
public List<Carro> load(int first, int pageSize,
String
sortField, SortOrder sortOrder, Map<String, Object> filters) {
List<Carro>
carros = carroDAO.buscarTodosPaginado(first, pageSize);
this.setRowCount(carroDAO.pegarQuantidadeDeCarros().intValue());
return carros;
}
}
Essa classe estende a classe LazyDataModel do primefaces, e
tem uma implementação bem simples. Preste bastante atenção quanto ao método load que deve ser sobrescrito,
que deve ser o segundo e não o primeiro. Note que os dois métodos que chamamos
do carroDAO (buscarTodosPaginado(first, pageSize) e pegarQuantidadeDeCarros()) precisam
ser criados, então vamos adicioná-los a classe CarroDAO.
public List<Carro>
buscarTodosPaginado(int primeiroDigito, int segundoDigito){
return em.createQuery("FROM Carro", Carro.class)
.setFirstResult(primeiroDigito)
.setMaxResults(segundoDigito)
.getResultList();
}
public Long pegarQuantidadeDeCarros(){
return em.createQuery("SELECT count(c) FROM Carro
c", Long.class)
.getSingleResult();
}
Agora
que já temos tudo feito na camada model, vamos a camada Controller que é responsável por fazer a ligação entre a View e a
Model. Na classe PesquisaCarroBean
vamos adicionar o objeto do tipo LazyCarro
que será inicializado no método init
que possui a anotação @PostConstruct
e também o seu método getter para
que a página XHTML possa ter acesso.
@ManagedBean
@ViewScoped
public
class PesquisaCarroBean implements Serializable{
private LazyCarro lazyCarros;
...
public LazyCarro getLazyCarros() {
return
lazyCarros;
}
...
@PostConstruct
public void init(){
lazyCarros
= new LazyCarros(new
CarroDAO);
...
}
...
}
Pronto, com isso já temos uma consulta paginada. Caso apareça
um erro informando e o “Lazy loading não foi implementado”, sugiro que
verifique o método load que você
sobrescreveu na classe LazyCarro, checando os parâmetros com estes:
load(int first, int pageSize, String
sortField, SortOrder sortOrder, Map<String, Object> filters){...}
Qualquer dúvida,
pode deixar nos comentários que tentarei ajudar no que for possível...