Dúvida Paginação JSF e JPA

17 respostas
S

Olá, pessoal, preciso criar uma paginação com JPA e JSF, estou com dúvidas. Aparentemente consegui fazer no DAO, porém tenho dúvidas de como obter isso na visão.
Abaixo o meu código no DAO e no ManagedBean respectivo:

Como fazer para "passar os parâmetros, do First e Max Results, assim, como próxima e anterior, é minha dúvida.
Obrigado.

DAO:
@SuppressWarnings("unchecked")
	public List<Empresa> buscarPorNome(String nome, int first, int max) {
		Criteria query = this.session.createCriteria(Empresa.class)
				.add(Restrictions.ilike("nome", nome, MatchMode.ANYWHERE))
				.addOrder(Order.asc("prioridade"));
		query.setFirstResult(first);
		query.setMaxResults(max);
		return query.list();

	}
ManagedBean:
public List<Empresa> buscarPorNome(ActionEvent event) {
		if (this.listaPesquisa == null) {
			EmpresaRN empresaRN = new EmpresaRN();
			listaPesquisa = empresaRN.buscaPorNome(empresa.getNome());
		}
		return this.listaPesquisa;
	}

17 Respostas

G

Talvez a melhor forma de fazer esta paginação não seja por este meio.

Não é mais fácil você buscar todas, sem limitar o resultado, e apresentar em um grid com paginação no grid. ?!

S

Você diz fazer um dataTable?(Primefaces ou RichFaces)
porque, se é essa a sugestão, pensava em tratar com recursos do próprio JSF, já que queria fazer o visual “no braço”, não ia usar esses recursos.
mas, beleza, qual é a sua sugestão?

S

Pensei em determinar um valor fixo para a lista para que pagine à partir de um número máximo de registros, na lógica, mais ou menso assim:
exibiria o primeiro registro ao clicar em “primeira”, ao clicar em “próxima” obteria a posição da lista e à partir dela passaria os outros resultados, com base no tamanho máximo da lista novamente. e ao clicar em anterior subtrairia certo valor para decrescer a posição da lista.

Essa era a dúvida na prática.

G

Ah entendi … Você deseja utilizar JSF, porém sem a suite de componentes.

A minha ideia era você utilizar a paginação de uma destas suitecases, mas se foco é outro.
Vou dar uma olhada aqui e ja te falo, no projeto que estou estamos fazendo paginação e tudo mais na mão …

G

smnj:
Pensei em determinar um valor fixo para a lista para que pagine à partir de um número máximo de registros, na lógica, mais ou menso assim:
exibiria o primeiro registro ao clicar em “primeira”, ao clicar em “próxima” obteria a posição da lista e à partir dela passaria os outros resultados, com base no tamanho máximo da lista novamente. e ao clicar em anterior subtrairia certo valor para decrescer a posição da lista.

Essa era a dúvida na prática.

Mas se for fazer desta forma que disse, não irá no banco a cada paginada, correto!?
Você já terá todos os registros e mãos e, ao navegar, irá apresentar um grupo de registro por vez …

Me entende ?!

S

Muito obrigado, Guilherme.

S

Realmente, Guilherme, é fato que talvez ganharia performance com isso, porém, preciso personalizar a exibição de um modo muito específico, por isso, realmente precisaria fazê-la “no braço”.

G

Conversei com o pessoal aqui e vi a nossa solução.
É um pouco complicado de explicar, vou entender melhor com o cara que criou e te mando a solução assim que puder.

S

Obrigado, Guilherme.
Caso precise meu e-mail é [email removido]

D

compartilhe conosco a solução…

Qual a vantagem de buscar tudo do banco e fazer apaginacao so na view?
O consumo de recursos será o mesmo, e se tiver 1kk de tuplas, e ai?

S

O que indica?
Realmente concordo que consumirá muito recurso…
Só estava pensando em personalizar a dataTable, o que recomenda?

S

Pensei em paginar do banco…
limitando a quantia de registros de dez em dez, passando um MaxResult(quantia máxima de resultados) e algum tipo de offset, que armazerne a posição da lista, mas não sei como fazer na prática.

D

poxa primefaces ia ser perfeito pra isso…

http://www.primefaces.org/showcase/ui/datatablePagination.jsf

sem ofenças mas… pq reinventar a roda???

não rola de armazenar esses valores no MB?
ai de acordo com o valor q o usuario solicitar ele vai no DB e busca???

H

Você pode utilizar o primefaces e paginar de modo lazy: Lazy JSF Datatable Pagination (Primefaces).

Desse modo você não precisa buscar ziguilhões de resultados para exibir na tela. Busca apenas o que é necessário para ser exibido.

Caso você não queira utilizar Primefaces mas criar sua própria pesquisa, você pode olhar nesse exemplo de como realizar uma consulta no DB paginada.

S

Muito obrigado, JakeFrog, olharei o seu post, mais uma vez, quebrando meu galho, valw, é bom contar com você.
Quanto ao colega, anterior, te agradeço realmente, apesar de gostar do primefaces e do richfaces, eles limitam bastante em alguns instantes o design.

G

Vamos a solução: (pode não ser a melhor, mas acho que atende o seu problema).

Esta classe em anexo tem a inteligencia total da paginacao, a parte mais dificil esta feita.

Objetivo: Você deve apresentar toda as possiveis paginas em tela (atributo numberOfPages do objeto Paginacao) e quando ele clicar em algums dos numeros, você coloque este numero dentro do atributo PAGE do objeto Paginacao.

é simples fazer isto: Você declara esta classe Paginacao como um atributo do seu managedBean e na tela mapeia que algum componente: #{mb.paginacao.page} quando foi feito o submit ou ajax, este valor já estará dentro deste objeto e neste mesmo submit você chamará o método pesquisar o qual irá passar ao service este objeto Paginação que já terá calculado o minResult e maxResult.

Dentro deste service você irá precisar descobrir uma coisa: a quantidade de registros que sua consulta vai retornar! você da um COUNT, passando seus parametros, na tabela e SETA o resultado dentro do objeto paginação, na propriedade totalOfRows.

Dai você faz uma busca dos registro, passando seus parametros. Dai você utiliza aquele DAO que você criou que recebe minResult e maxResult, passando as propriedades getFirstResult e getMaxResult do objeto Paginacao, respectivamente.

Retorna a lista de registros e apresenta em tela.

Existe um atributo do objeto Paginacao, numberOfPages, que terá todas as possiveis páginas (link todos estes numeros para que ao submitar a página ele ENVIE o valor do número da página para o atributo PAGE, o que mencionei acima) . Apresente-o na tela juntamente com seu grupo de registros, quando o usário clicar em um destes números o objeto paginação terá a pagina desejada e irá ter o maxResult e firstResult prontos para seu DAO trazer a quantidade de registros corretamente.

Segue a classe que tem a inteligencia de paginar, ela deve ser trafegada até o DAO para receber o valor do count, como também passar o valor do minResult e maxResult

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

public class Paginacao implements Serializable {
    
    private static final long serialVersionUID = -1L;


    /**
     * Página corrente
     */
    private int page = 1;
    
    /**
     * Divisor de página.
     */
    private Float pageDivisor = (float) 10;
    
    /**
     * Total de registros
     */
    private Float totalOfRows = 0F;
    
    /**
     * List quantidade de páginas
     */
    private List<Integer> numberOfPages = new LinkedList<Integer>();
    
    /**
     * Retorna o primeiro indice da paginacao
     */
    public int getFirstResult(){
        int firstResult = (int) ((page-1) * pageDivisor);
        
        return firstResult >= 0 ? firstResult : 0;
    }
    
    /**
     * Retorna último indice de paginacao 
     */
    public int getMaxResult(){
        return pageDivisor.intValue();
    }

    public void setTotalOfRows(float totalOfRows) {
        this.totalOfRows = totalOfRows;
        
        numberOfPages = new LinkedList<Integer>();
        int qtd = ((Double) Math.ceil(this.totalOfRows / pageDivisor)).intValue();
        
        for(int i=1; i<= qtd; i++){
            numberOfPages.add(i);
        }            
    }
    
    public void setPageDivisor(int pageDivisor) {
        this.pageDivisor = new Float(pageDivisor);
    }
    
    public int getPageDivisor() {
        return pageDivisor.intValue();
    }
    
    public List<Integer> getDivisors(){
        List<Integer> lst = new LinkedList<Integer>();
        lst.add(5);
        lst.add(10);
        lst.add(25);
        lst.add(50);
        lst.add(100);
        
        return lst;        
    }
    

    public int getTotalOfPages() {
        return numberOfPages.size();
    }

    
    public int getTotalOfRows() {
        return totalOfRows.intValue();
    }
    
    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public List<Integer> getNumberOfPages() {
        return numberOfPages;
    }   
}

Acho que isto já lhe dará um LUZ para este problema.

S

Obrigado, vou trabalhar nesta idéia.

Criado 16 de julho de 2012
Ultima resposta 17 de jul. de 2012
Respostas 17
Participantes 5