Lazy Loading em DataGrid do PrimeFaces 3.0.1

Boa tarde, pessoal.

Tivemos que criar um esquema de lazy loading para o DataGrid do Primefaces versão 3.0.1.

Segue o esquema que utilizamos para apreciação de quem mais precise dessa funcionalidade!

public List<Cliente> getValues() {
        
        ExternalContext ec = null;

        try {

            ec = FacesContext.getCurrentInstance().getExternalContext();

        } catch (Exception e) {
            e.printStackTrace();
        }
        
        //DataGrid dataGrid = (DataGrid) FacesContext.getCurrentInstance().getViewRoot().findComponent(DATAGRID_NAME);
        
        Map<String, String[]> params = ec.getRequestParameterValuesMap();
        
        int first = 0, max = 0;

        try {
        
            String paramFirst = params.get(DATAGRID_NAME + "_first")[0];

            String paramMax = params.get(DATAGRID_NAME + "_rows")[0]; 

            first = Integer.valueOf(paramFirst);
            
            max = Integer.valueOf(paramMax);
            
            System.out.println("NEW PAGINATION -----> (" + first + ", " + max + ")");
            
        } catch(Throwable t) {
            t.printStackTrace();
            first = 0;
            max = PAGE_SIZE;
        }
        
        int last = first + max;
        
        int rowCount = dao.getRowCount();
        
        if(last > rowCount) {
            last = rowCount;
        }
        try {
            return new ArrayList<Cliente>(Arrays.asList(Arrays.copyOf(dao.find(first, last).toArray(new Cliente[]{}), rowCount)));
        } catch (AccessException ex) {
            Logger.getLogger(ClienteBean.class.getName()).log(Level.SEVERE, null, ex);
            return new ArrayList<Cliente>(0);
        }
        
    }

Sendo que dao é o objeto que busca os registros no banco de dados.

Abraço!

Legal.

Valeu por compartilhar. [=

Boa noite, fiz uma implementação diferente, e também gostaria de compartilhar, e tabém ouvir possiveis criticas e melhorias.

Pagina

			<h:form>
                <p:dataTable value="#{index.data}" var="item" rows="10">
                    <p:column headerText="Nome" sortBy="#{item.name}" filterBy="#{item.name}">
                        <h:outputText value="#{item.name}"/>
                    </p:column>
                    <p:column headerText="Addressline1" sortBy="#{item.addressline1}" filterBy="#{item.addressline1}">
                        <h:outputText value="#{item.addressline1}"/>
                    </p:column>
                    <p:column headerText="Addressline2" sortBy="#{item.addressline2}" filterBy="#{item.addressline2}">
                        <h:outputText value="#{item.addressline2}"/>
                    </p:column>
                </p:dataTable>
            </h:form>

ManagedBean

package com.lazilist.mb;

import com.lazilist.commons.LazyList;
import com.lazilist.entity.Customer;
import com.lazilist.repo.CustomerFacade;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;

@ManagedBean
@ViewScoped
public class Index {

    @Inject
    private CustomerFacade customerFacade;//Aqui é uma implementação do AbstractFacade<T>
    private LazyList<Customer> data;
    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public LazyList<Customer> getData() {
        if (data == null) {
            data = new LazyList(customerFacade);
        }
        return data;
    }

    public void setData(LazyList<Customer> data) {
        this.data = data;
    }
}

LazyList, aqui está a implementação

package com.lazilist.commons;

import com.lazilist.repo.AbstractFacade;
import java.util.List;
import java.util.Map;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

public class LazyList<T> extends LazyDataModel<Beanable> {

    private AbstractFacade<Beanable> facade;

    public LazyList(AbstractFacade<Beanable> facade) {
        this.facade = facade;
    }
    private static final long serialVersionUID = 1L;
    protected List<Beanable> data;

    @Override
    public List<Beanable> load(int startingAt, int maxPerPage, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        data = facade.getByRangeSortFilter(startingAt, maxPerPage, sortField, sortOrder, filters);
        setRowCount(facade.countFilter(filters));
        setPageSize(maxPerPage);
        return data;
    }

    @Override
    public Object getRowKey(Beanable bean) {
        return bean.getId();
    }

    @Override
    public Beanable getRowData(String beanId) {
        if (beanId != null && !beanId.equals("") && !beanId.equals("null")) {
            Object id = Integer.valueOf(beanId);
            for (Beanable bean : data) {
                if (id.equals(bean.getId())) {
                    return bean;
                }
            }
        }
        return null;
    }
}

Beanable

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.lazilist.commons;

/**
 *
 * @author flavio
 */
public interface Beanable {
    
    public Object getId();
    
}

Metodos nescessarios no AbstractFacade

public List<T> getByRangeSortFilter(int startingAt, int maxPerPage, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<T> q = cb.createQuery(entityClass);
        Root<T> c = q.from(entityClass);
        q.select(c);
        if (filters != null && !filters.isEmpty()) {
            Predicate[] predicates = new Predicate[filters.size()];
            int i = 0;
            for (Map.Entry<String, String> entry : filters.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                Expression<String> path = c.get(key);
                try {
                    if (entityClass.getDeclaredField(key).getType().equals(String.class)) {
                        predicates[i] = cb.and(cb.like(path, "%" + val + "%"));
                    } else {
                        predicates[i] = cb.and(cb.equal(path, val));
                    }
                } catch (NoSuchFieldException ex) {
                    Logger.getLogger(AbstractFacade.class.getName()).log(Level.SEVERE, null, ex + " entityClass:" + entityClass.toString());
                } catch (SecurityException ex) {
                    Logger.getLogger(AbstractFacade.class.getName()).log(Level.SEVERE, null, ex + " entityClass:" + entityClass.toString());
                }
                i++;
            }
            q.where(predicates);
        }
        if (sortField != null && !sortField.isEmpty()) {
            if (sortOrder.equals(SortOrder.ASCENDING)) {
                q.orderBy(cb.asc(c.get(sortField)));
            } else if (sortOrder.equals(SortOrder.DESCENDING)) {
                q.orderBy(cb.desc(c.get(sortField)));
            }
        }
        TypedQuery<T> query = getEntityManager().createQuery(q);
        query.setMaxResults(maxPerPage);
        query.setFirstResult(startingAt);
        return query.getResultList();
    }

    public int countFilter(Map<String, String> filters) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery q = cb.createQuery(entityClass);
        Root<T> c = q.from(entityClass);
        q.select(cb.count(c));
        if (filters != null && !filters.isEmpty()) {
            Predicate[] predicates = new Predicate[filters.size()];
            int i = 0;
            for (Map.Entry<String, String> entry : filters.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                Expression<String> path = c.get(key);
                try {
                    if (entityClass.getDeclaredField(key).getType().equals(String.class)) {
                        predicates[i] = cb.and(cb.like(path, "%" + val + "%"));
                    } else {
                        predicates[i] = cb.and(cb.equal(path, val));
                    }
                } catch (NoSuchFieldException ex) {
                    Logger.getLogger(AbstractFacade.class.getName()).log(Level.SEVERE, null, ex + " entityClass:" + entityClass.toString());
                } catch (SecurityException ex) {
                    Logger.getLogger(AbstractFacade.class.getName()).log(Level.SEVERE, null, ex + " entityClass:" + entityClass.toString());
                }
                i++;
            }
            q.where(predicates);
        }
        TypedQuery<T> query = getEntityManager().createQuery(q);
        return ((Long) query.getSingleResult()).intValue();
    }

Como eu disse podem criticar, mas espero que que seja útil para alguem.

[quote=AmauriSpPoa]Boa noite, fiz uma implementação diferente, e também gostaria de compartilhar, e tabém ouvir possiveis criticas e melhorias.[/quote]A sua é a implementação sugerida pelo próprio criador do Primefaces. Que é a normal de se encontrar.

Quem quiser um tutorial tem aqui: Lazy JSF Datatable Pagination (Primefaces).

O que eu achei legal da idéia do hollywoodpanda é que ele simplifica a utilização. Não foi necessário utilizar o LazyDataModel.

Apenas um MB e pronto. [=

Eu ainda não sei como realmente fica em questão de utilização desse código com o Ajax do Primefaces (que normalmente é utilizado) e se toda vez que esse método é chamado, se ele irá disparar a consulta.

Mas achei uma abordagem muito interessante. [=

hollywoodpanda, não se esqueça que getValues() será chamada várias vezes por causa do ciclo de vida do JSF!!! É necessário ter algum tipo de cache.

[]'s

Olá Pessoal,

Consegui implementar a solução sugerida pelo Hebert e o exemplo do primefaces. Atualmente estou com a versão do tutorial do primefaces, mas não estou conseguindo utilizar o filtro, não filtra nada.

Obrigado.


public class ParticipLazyList extends LazyDataModel<Participante> {  
      
    private List<Participante> datasource;  
      
    public ParticipLazyList(List<Participante> datasource) {  
        this.datasource = datasource;  
    }  
      
    @Override  
    public Participante getRowData(String rowKey) {  
        for(Participante participante : datasource) {  
            if(participante.getCodigo().equals(rowKey))  
                return participante;  
        }    
        return null;  
    }  
  
    @Override  
    public Object getRowKey(Participante participante) {  
        return participante.getCodigo();  
    }  
  
    @Override  
    public List<Participante> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters) {  
        List<Participante> data = new ArrayList<Participante>();  
  
        System.out.println("ParticipLazyList");
        System.out.println(sortField);
        System.out.println(filters);

        //filter  
        for(Participante participante : datasource) {  
            System.out.println("filter");
            
            boolean match = true;  
  
            for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {  
                try {  
                    String filterProperty = it.next();  
                    String filterValue = filters.get(filterProperty);  
                    String fieldValue = String.valueOf(participante.getClass().getField(filterProperty).get(participante));  
  
                    if(filterValue == null || fieldValue.startsWith(filterValue)) {  
                        match = true;  
                    }  
                    else {  
                        match = false;  
                        break;  
                    }  
                } catch(Exception e) {  
                    match = false;  
                }   
            }  
            System.out.println("filter - 000");                
            System.out.println(participante.getCodigo());                
            
            if(match) {  
                System.out.println("filter - 001");                
                System.out.println(participante.getCodigo());                
                data.add(participante);  
            }  
        }