Lazy datatable do primefaces+filtering

Fala galera, estou com dificuldades para implementar o filtering em uma lazy datatable do primefaces, principalmente na hora de implementar o codigo de pesquisar por nome no dao generico e acredito que necessitarei dele no DataModelCliente na hora de setar o filtro, olhei inumeros exemplos mas falhei miseravelmente, tanto que na classe eu tentei sem ser generico mesmo então desconsiderem :oops:
eu consegui fazer paginação e implementar o lazy seguindo exemplos da caelum então tudo está bem padrão de apostila mesmo…
se alguem puder me dar uma luz…

segue minhas classes

-Dao generico

public class DAO<T> implements Serializable {

	private final Class<T> classe;

	public DAO(Class<T> classe) {
		this.classe = classe;
	}
//...

//metodo que lista todos clientes
public List<T> listaTodos() {
		EntityManager em = new JPAUtil().getEntityManager();
		CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(classe);
		query.select(query.from(classe));

		List<T> lista = em.createQuery(query).getResultList();

		em.close();
		return lista;
	}

	public T buscaPorId(Long id) {
		EntityManager em = new JPAUtil().getEntityManager();
		T instancia = em.find(classe, id);
		em.close();
		return instancia;
	}

	public int contaTodos() {
		EntityManager em = new JPAUtil().getEntityManager();
		long result = (Long) em.createQuery(
				"select count(n) from " + classe.getName() + " n")
				.getSingleResult();
		em.close();

		return (int) result;
	}
//metodo que uso para paginacao de todos
	public List<T> listaTodosPaginada(int firstResult, int maxResults) {
		EntityManager em = new JPAUtil().getEntityManager();
		CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(classe);
		query.select(query.from(classe));

		List<T> lista = em.createQuery(query).setFirstResult(firstResult)
				.setMaxResults(maxResults).getResultList();

		em.close();
		return lista;
	}

//+- o metodo que pensei em buscar pelo nome do cliente, mas gostaria q fosse generico
	public List<Cliente> buscaPorNome(String nomeCliente) {
		EntityManager em = new JPAUtil().getEntityManager();
		String jpql = "select c from Cliente c where lower(c.nomeCliente) like :nomeCliente"
				+ " order by c.nomeCliente";
		TypedQuery<Cliente> query = em.createQuery(jpql, Cliente.class);
		query.setParameter("nomeCliente", "%" + nomeCliente + "%");
		return query.getResultList();
	}

-ClienteBean

@ViewScoped
@Named
public class ClienteBean implements Serializable {

	private Cliente cliente = new Cliente();
	private List<Cliente> clientes;
	private Long clienteIdCliente;
	@Inject
	private DAO<Cliente> dao;

//...

               //metodo que lista todos clientes
	public List<Cliente> getClientes() {
		if (clientes == null) {
			System.out.println("Carregando lista de clientes...");
			clientes = new DAO<Cliente>(Cliente.class).listaTodos();
		}
		return clientes;
	}
             //metodo que eu usaria para pegar o nome, pensei em algo assim mas creio que nao esta certo
	public List<Cliente> buscaNome(String nome) {

		return dao.buscaPorNome(nome);

	}

ListaClientesBean

@ViewScoped
@Named
public class ListaClientesBean implements Serializable {

	private LazyDataModel<Cliente> dataModel;

	public ListaClientesBean() {
		this.dataModel = new DataModelCliente();
		DAO<Cliente> dao = new DAO<Cliente>(Cliente.class);
		this.dataModel.setRowCount(dao.contaTodos());
		this.dataModel.setPageSize(5);
	}

	public LazyDataModel<Cliente> getDataModel() {
		return dataModel;
	}

DataModelCliente

public class DataModelCliente extends LazyDataModel<Cliente> {

	public List<Cliente> load(int inicio, int quantidade,
			String campoOrdenacao, SortOrder sentidoOrdenacao,
			Map<String, String> filtros) {

		DAO<Cliente> dao = new DAO<Cliente>(Cliente.class);

		return dao.listaTodosPaginada(inicio, quantidade);

	}

cliente.xhtml
minha duvida aqui tb é se o filteredValue teria q filtrar pelo metodo do ClienteBean(buscaNome) ou se ja era possivel passar de algum modo no listaClientesBean mesmo

<p:dataTable value="#{listaClientesBean.dataModel}" widgetVar="clientesTable" emptyMessage="nenhum cliente com esses parametros foram encontrados" filteredValue="#{clienteBean.buscaNome}" id="display" var="cliente" paginator="true" rows="5" lazy="true" dynamic="true" styleClass="dados" rowClasses="impar,par" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15">


<p:column headerText="Nome" id="colunaNome" filterBy="#{cliente.nomeCliente}"  filterMatchMode="contains">
<h:outputText value="#{cliente.nomeCliente}"/>
</p:column>
<p:column headerText="CPF">
#{cliente.cpfCliente}
</p:column>
<p:column headerText="RG">
#{cliente.rgCliente}
</p:column>

Olá amigo, recomendo você setar ordem na propria consulta. Se não me engano ele te manda um mapa de objetos, dai vc pega esse mapa incrementa na sua consulta.

Vi que você não está utilizando criteria, no seu caso iria pegando cada um e add um “AND” no where pegando seus valores, seja com LIKE ou IN, Etc

Pessoal,

Fiz um DAO Genérico com Paginação e Primefaces. Funciona de boa!!!

package br.com.schimidtsolutions.jsf.dao;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;

import org.hibernate.jpa.criteria.OrderImpl;
import org.slf4j.Logger;

import br.com.schimidtsolutions.jsf.dao.helper.Paginacao;
import br.com.schimidtsolutions.jsf.util.MetodoObjetoUtil;

class DAOGenerico<T> implements DAO<T> {
	private static final long serialVersionUID = 6020966045581794498L;

	@Inject @Singleton
	private Logger log;
	
	@NotNull(message="A classe genérica do DAO não pode ser nula!")
	private final Class<T> classeEntidade;
	
	@NotNull(message="O EntityManager não pode ser nulo para o DAOGenérico!")
	private final EntityManager em;
	
	public DAOGenerico(final Class<T> classEntity, final EntityManager em) {
		this.classeEntidade = classEntity;
		this.em = em;
	}
	
	@Override
	public T adicionar( final T entidade ){
		em.persist( entidade );
		
		return entidade;
	}
	
	@Override
	public <ID> T pesquisarPorId( final ID id ){
		return em.find( classeEntidade, id );
	}
	
	@Override
	public Long contar(){
		final CriteriaBuilder builder = em.getCriteriaBuilder();
		final CriteriaQuery<Long> query = builder.createQuery( Long.class );
		
		query.select( builder.countDistinct( query.from( classeEntidade ) ) );
		
		return em.createQuery( query ).getSingleResult();
	}
	
	public List<T> listarComPaginacaoOrdenacaoEFiltros( Paginacao paginacao ){
		return criarTypedQueryParaPaginacao(paginacao).getResultList();
	}

	private TypedQuery<T> criarTypedQueryParaPaginacao( Paginacao paginacao ) {
		final CriteriaBuilder builder = em.getCriteriaBuilder();
		final CriteriaQuery<T> query = builder.createQuery( classeEntidade );
		
		final Root<T> tabela = query.from( classeEntidade );
		
		final Order ordem = criarOrdemPaginacao( paginacao, tabela );
		final Predicate where = criarPredicatePaginacao( paginacao, builder, tabela );
		
		return criarTypedQueryPorParametros( query, tabela, ordem, where, paginacao );
	}

	private TypedQuery<T> criarTypedQueryPorParametros(final CriteriaQuery<T> query, final Root<T> tabela, Order ordem, Predicate where, Paginacao paginacao) {
		
		CriteriaQuery<T> queryPaginacao = query.select( tabela );
		
		if( where != null ){
			queryPaginacao = queryPaginacao.where( where );
		}
		
		if( ordem != null ){
			queryPaginacao = queryPaginacao.orderBy( ordem );
		}
		
		return em.createQuery( queryPaginacao )
				.setFirstResult( paginacao.getPaginaInicial() )
				.setMaxResults( paginacao.getTamanhoPagina() );		
	}

	private Predicate criarPredicatePaginacao( Paginacao paginacao, final CriteriaBuilder builder, final Root<T> tabela ) {
		Predicate where = null;
		
		if( paginacao.getFiltros() != null && !paginacao.getFiltros().isEmpty() ){
			where = builder.and();
			
			for( String nomeCampoTabela : paginacao.getFiltros().keySet() ){
				Expression<String> campoTabela = tabela.get( nomeCampoTabela );
				Object valorProcurado = paginacao.getFiltros().get( nomeCampoTabela );
				
				campoTabela.as( campoTabela.getJavaType() );
				
				if( campoTabela.getJavaType().equals( String.class ) ){
					where = builder.and( where, 
						builder.like( 
							builder.lower( campoTabela ), 
								String.format("%%%s%%", ((String) valorProcurado).toLowerCase() ) ) );
						
				}else{
					where = builder.and( where, builder.equal( campoTabela, valorProcurado ) );
				}
			}
		}
		
		return where;
	}

	private Order criarOrdemPaginacao(Paginacao paginacao, final Root<T> tabela) {
		
		if( paginacao.getOrdenacao() != null && paginacao.getOrdenacao().getMetodoOrdenacao() != null ){
			return new OrderImpl( tabela.get( paginacao.getOrdenacao().getCampoOrdenado() ), 
					paginacao.getOrdenacao().getMetodoOrdenacao().isAscendente() );
		}
		
		return null;
	}
		
	@Override
	public List<T> listarTudo(){
		final TypedQuery<T> typedQuery = gerarTypedQuerySemWhere();
		
		return typedQuery.getResultList();
	}

	private TypedQuery<T> gerarTypedQuerySemWhere() {
		final CriteriaBuilder builder = em.getCriteriaBuilder();
		final CriteriaQuery<T> query = builder.createQuery( classeEntidade );
		
		final Root<T> from = query.from( classeEntidade );
		
		final TypedQuery<T> typedQuery = em.createQuery(  query.select( from ) );
		
		return typedQuery;
	}
	
	@Override
	public T atualizar( final T entidade ){
		return em.merge( entidade );
	}

	@Override
	public <ID> void apagarPorId(final ID IdEntidade) {
		em.remove( pesquisarPorId( IdEntidade ) );		
	}

	@Override
	public void apagar(final T entidade) {
		em.remove( em.merge( entidade ) );
	}

	@Override
	public List<T> pesquisarPorCamposIguaisPreenchidos(final T entidade) {
		final CriteriaBuilder builder = em.getCriteriaBuilder();
		final CriteriaQuery<T> query = builder.createQuery( classeEntidade );
		final Root<T> from = query.from( classeEntidade );
		
		final Predicate predicate = gerarPredicateDinamicoCamposPreenchidos(builder, from, entidade );
		
		final TypedQuery<T> typedQuery = em.createQuery( query.select( from ).where( predicate ) );	
		
		return typedQuery.getResultList();
	}

	private Predicate gerarPredicateDinamicoCamposPreenchidos( final CriteriaBuilder builder, final Root<T> from, final T entidade ) {
		
		Predicate predicate = builder.and();
		
		for( final Method method : entidade.getClass().getDeclaredMethods() ){
					
			try {
				if( MetodoObjetoUtil.isMetodoGetter( method ) ){
					final Object valorCampo = method.invoke( entidade, (Object[]) null);
				
					if( valorCampo != null ){
						final String nomeCampo = MetodoObjetoUtil.obterNomeCampoPeloMetodoAcessorio( method );						
						
						predicate = builder.and( predicate, 
								builder.equal( from.get( nomeCampo ), valorCampo ) );
					}
				}
				
			} catch (final IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
				log.warn( "Erro no método DAOGenerico<T>.gerarPredicateDinamicoCamposPreenchidos", e );
			}
		}
		
		return predicate;
	}
}