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

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:

[code]<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ó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>[/code]

[code]@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;
}

}[/code]

[code]public class LazyLocalDataModel extends LazyDataModel {

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();
}

}[/code]

[code]@Repository
@Transactional(“gsmTM”)
public class LocalFacade extends AbstractFacade {

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);
}

}[/code]

[code]public abstract class AbstractFacade {

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();
}

}[/code]

veja exemplo na vida real funcionando

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

[quote=jvhexa]veja exemplo na vida real funcionando

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

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