Primefaces LazyDataModel multiple sort - perdendo ordenação ao clicar na paginação

2 respostas
M

Bom pessoal, estou passando por um problema e não estou conseguindo resolver, nem com a ajuda do google.

O problema é na implementação do LazyDataModel do Primefaces 3.5, quando utilizo:

sortMode="single" - a ordenação funciona corretamente.

sortMode="multiple" - na primeira pagina, quando clico nas colunas, a ordenação é feita corretamente, mas quando clico para ir na pagina 2, 3,... a ordenação é perdida.

Segue meu codigo:

<p:dataTable lazy="true" sortMode="multiple" paginator="true" rows="15" rowsPerPageTemplate="15,20,25"
             paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
             value="#{locaisController.lazyModel}" var="loc">
    <p:column headerText="C&oacute;digo" sortBy="#{loc.codLocal}" filterBy="#{loc.codLocal}" >
        <h:outputText value="#{loc.codLocal}" />
    </p:column>
    <p:column headerText="Nome" sortBy="#{loc.nome}" filterBy="#{loc.nome}" >
        <h:outputText value="#{loc.nome}" />
    </p:column>

</p:dataTable>
@Controller
@Scope("view")
public class LocaisController {

    private Short unidade;
    private LazyDataModel<Local> lazyModel = null;
    private LocalFacade localFacade;
    Logger logger = Logger.getLogger(LocaisController.class);

    @Autowired
    public LocaisController(LocalFacade localFacade) {
        this.localFacade = localFacade;
    }

    @PostConstruct
    public void init() {
        unidade = 10;
    }

    public void lazyLoad() {
        Map<String, String> filtros = new HashMap<String, String>();
        filtros.put("unidade", unidade.toString());
        lazyModel = new LazyLocalDataModel(localFacade, filtros);
    }

    public LazyDataModel<Local> getLazyModel() {
        if (lazyModel == null) {
            lazyLoad();
        }
        return lazyModel;
    }
    
    public Short getUnidade() {
        return unidade;
    }

    public void setUnidade(Short unidade) {
        this.unidade = unidade;
    }
}
public class LazyLocalDataModel extends LazyDataModel<Local> {

    private LocalFacade localFacade;
    private Map<String, String> customFilters;

    public LazyLocalDataModel(LocalFacade localFacade, Map<String, String> customFilters) {
        this.localFacade = localFacade;
        this.customFilters = customFilters;
    }
    protected List<Local> data;

    @Override
    public List<Local> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, String> filters) {
        data = localFacade.findByUnidade(first, pageSize, multiSortMeta, filters, customFilters);
        setRowCount(localFacade.getRowCount());
        setPageSize(pageSize);
        return data;
    }

    @Override
    public List<Local> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        data = localFacade.findByUnidade(first, pageSize, sortField, sortOrder, filters, customFilters);
        setRowCount(localFacade.getRowCount());
        setPageSize(pageSize);
        return data;
    }
    
    @Override
    public Local getRowData(String rowKey) {
        for (Local local : this) {
            if (local.getCodLocal().equals(Short.parseShort(rowKey))) {
                return local;
            }
        }
        return null;
    }

    @Override
    public Object getRowKey(Local local) {
        return local.getCodLocal();
    }
}
@Repository
@Transactional("gsmTM")
public class LocalFacade extends AbstractFacade<Local> {

    protected EntityManager entityManager;

    @PersistenceContext(unitName = "gsmPU")
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    protected EntityManager getEntityManager() {
        return entityManager;
    }

    public LocalFacade() {
        super(Local.class);
    }

    // ##################################################### LazyDataModelLoad #####################################################
    @Override
    protected List<Predicate> lazyLoadCustomFilters(CriteriaBuilder criteriaBuilder, Root<Local> from, Map<String, String> customFilters) {
        List<Predicate> predicates = new ArrayList<Predicate>();
        for (Map.Entry<String, String> entry : customFilters.entrySet()) {
            if (entry.getKey().equals("unidade")) {
                predicates.add(criteriaBuilder.equal(from.get("unidade"), Short.parseShort(entry.getValue())));
            }
        }
        return predicates;
    }

    @Override
    protected List<Order> lazyLoadSortDefault(CriteriaBuilder criteriaBuilder, Root<Local> from) {
        logger.info("ordenacao inicial");
        List<Order> sorts = new ArrayList<Order>();
        sorts.add(criteriaBuilder.asc(from.get("codLocal")));
        sorts.add(criteriaBuilder.asc(from.get("nome")));
        return sorts;
    }

    public List<Local> findByUnidade(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, String> filters, Map<String, String> customFilters) {
        return lazyLoad(first, pageSize, null, null, multiSortMeta, filters, customFilters);
    }

    public List<Local> findByUnidade(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters, Map<String, String> customFilters) {
        return lazyLoad(first, pageSize, sortField, sortOrder, null, filters, customFilters);
    }
}
public abstract class AbstractFacade<T> {

    private Class<T> entityClass;
    Logger logger = Logger.getLogger(AbstractFacade.class);

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    // ##################################################### LazyDataModelLoad #####################################################
    private int rowCount;

    public int getRowCount() {
        return rowCount;
    }

    protected abstract List<Predicate> lazyLoadCustomFilters(CriteriaBuilder criteriaBuilder, Root<T> from, Map<String, String> customFilters);

    protected abstract List<Order> lazyLoadSortDefault(CriteriaBuilder criteriaBuilder, Root<T> from);

    public List<T> lazyLoad(int first, int pageSize, String sortField, SortOrder sortOrder, List<SortMeta> multiSortMeta, Map<String, String> filters, Map<String, String> customFilters) {
        logger.info("first: " + first + ", pageSize: " + pageSize);
        // criteria
        CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);

        // from
        Root<T> from = criteriaQuery.from(entityClass);
        criteriaQuery.select(from);

        // sort 
        criteriaQuery.orderBy(lazyLoadSorter(sortField, sortOrder, multiSortMeta, from, criteriaBuilder));

        // filters 
        List<Predicate> predicates = lazyLoadFilters(filters, customFilters, from, criteriaBuilder);
        criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));

        // consulta
        TypedQuery<T> query = getEntityManager().createQuery(criteriaQuery);
        query.setFirstResult(first);
        query.setMaxResults(pageSize);

        // count        
        rowCount = lazyLoadRowCount(criteriaBuilder, predicates);

        return query.getResultList();
    }

    private List<Predicate> lazyLoadFilters(Map<String, String> filters, Map<String, String> customFilters, Root<T> from, CriteriaBuilder criteriaBuilder) {
        List<Predicate> predicates = new ArrayList<Predicate>();

        if (customFilters != null) {
            predicates = lazyLoadCustomFilters(criteriaBuilder, from, customFilters);
        }

        if (filters != null) {
            for (Map.Entry<String, String> entry : filters.entrySet()) {
                Expression value = criteriaBuilder.literal("%" + entry.getValue() + "%");
                Expression field = criteriaBuilder.lower(from.get(entry.getKey()).as(String.class));
                logger.info(entry.getKey() + ": " + entry.getValue());
                predicates.add(criteriaBuilder.like(field, value));
            }
        }
        return predicates;
    }

    private List<Order> lazyLoadSorter(String sortField, SortOrder sortOrder, List<SortMeta> multiSortMeta, Root<T> from, CriteriaBuilder criteriaBuilder) {
        if (sortField != null) {
            return lazyLoadSingleSorter(sortField, sortOrder, from, criteriaBuilder);
        } else if (multiSortMeta != null) {
            return lazyLoadMultiSorter(multiSortMeta, from, criteriaBuilder);
        } else {
            return lazyLoadSortDefault(criteriaBuilder, from);
        }
    }

    private List<Order> lazyLoadMultiSorter(List<SortMeta> multiSortMeta, Root<T> from, CriteriaBuilder criteriaBuilder) {
        List<Order> sorts = new ArrayList<Order>();
        logger.info("MultiSort");
        for (SortMeta sortMeta : multiSortMeta) {
            if (sortMeta.getSortOrder() == SortOrder.ASCENDING) {
                sorts.add(criteriaBuilder.asc(from.get(sortMeta.getSortField())));
                logger.info("ASCENDING");
            } else {
                sorts.add(criteriaBuilder.desc(from.get(sortMeta.getSortField())));
                logger.info("DESCENDING");
            }
        }
        return sorts;
    }

    private List<Order> lazyLoadSingleSorter(String sortField, SortOrder sortOrder, Root<T> from, CriteriaBuilder criteriaBuilder) {
        List<Order> sorts = new ArrayList<Order>();
        logger.info("SingleSort");
        if (sortOrder == SortOrder.ASCENDING) {
            sorts.add(criteriaBuilder.asc(from.get(sortField)));
            logger.info("ASCENDING");
        } else {
            sorts.add(criteriaBuilder.desc(from.get(sortField)));
            logger.info("DESCENDING");
        }
        return sorts;
    }

    private int lazyLoadRowCount(CriteriaBuilder criteriaBuilder, List<Predicate> predicates) {
        CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
        countQuery.select(criteriaBuilder.count(countQuery.from(entityClass)));
        countQuery.where(predicates.toArray(new Predicate[predicates.size()]));

        return getEntityManager().createQuery(countQuery).getSingleResult().intValue();
    }
}

2 Respostas

J

veja exemplo na vida real funcionando

http://www.asmelhorespraticas.com.br/blog/1/entry-5-exemplo-lazydatamodel-primefaces-na-vida-real/

M

jvhexa:
veja exemplo na vida real funcionando

http://www.asmelhorespraticas.com.br/blog/1/entry-5-exemplo-lazydatamodel-primefaces-na-vida-real/

nesse exemplo não esta implementado o multiple sort … :confused:

Criado 28 de maio de 2013
Ultima resposta 22 de out. de 2013
Respostas 2
Participantes 2