Problema com paginação JSF + Richfaces

Boa noite! Pesquisei, pesquisei e pesquisei, testei, testei e testei… mas ainda não encontrei nada que me desse uma luz na resolução deste problema. Então, resolvi fazer meu primeiro tópico aqui.

É o seguinte. Tenho um bean que contém uma listagem. Essa listagem é preenchida por uma procedure.
Essa consulta já é paginada no banco de dados. Então, ela recebe a quantidade de registros que podem ser mostrados na tela, mais o número da página que está sendo pesquisada.

Ocorre que quem implementou a lógica, para paginar, incluiu registros nulos na lista para que desse o total de registros do banco.

Vou colocar um trecho do código (não posso colocar td por questões contratuais… =/)

MeuBean:

 List<MinhaClasse> listaAUX = new ArrayList<MinhaClasse>();
        
        if( minhaLista.size() > 0){
        	for (int i = 0; i < minhaLista.get(0).getTotalRegistrosBanco(); i++){
            	Integer linha = (( getPagina() * getRowsPerPage()) - getRowsPerPage());
            	if ( linha == i){
            		listaAUX.addAll(minhaLista);
            		i += (minhaLista.size() - 1);        		
            	}else{
            		listaAUX.add(i, null);            	
            	}        	         	        		
            }	
        }
                
        minhaLista.clear();
        minhaLista.addAll(listaAUX);

No trecho acima se eu tenho 14 registros no banco e tenho que mostrar 10 na primeira página, ele completa com 4 nulos… Se eu utilizo o sortBy do meu xhtml, ele joga os nulos para cima (cada linha tem um botão de editar e excluir, passando o id)

meuXHTML

<rich:dataTable value="#{meuBean.minhaLista}"
						binding="#{meuBean.dataTableMinhaLista}"
						var="minhaLista" id="tableResult"
						rows="#{meuBean.rowsPerPage}"
						rowClasses="rowOdd,rowEven" styleClass="noBorder" width="920px"
						headerClass="headerTable" immediate="true" rowKeyVar="idx"
						>

.
.
.
<span
					style="cursor: hand; cursor: pointer; float: left; positon: relative;"
					class="rich-datascr-button" id="xpto"
					onclick="Event.fire(document.getElementById('formTable:dataResultScroller_table'), 'rich:datascroller:onscroll', {'page': 'first'});">
					«« </span>
					
				<rich:datascroller for="tableResult" maxPages="3"
					styleClass="noBorder" boundaryControls="hide"
					style="float:left; positon: relative;" stepControls="hide"
					fastControls="hide" ajaxSingle="false" id="dataResultScroller"
					actionListener="#{meuBean.pesquisarActionListener}"										 					
					onbeforedomupdate="Richfaces.hideModalPanel('panelStatusPesquisaRel');"					
					 />
					
				<span
					style="cursor: hand; cursor: pointer; float: left; positon: relative;"
					class="rich-datascr-button" id="xpto1"
					onclick="Event.fire(document.getElementById('formTable:dataResultScroller_table'), 'rich:datascroller:onscroll', {'page': 'last'});">
					»» </span>
					
				<h:inputText value="#{meuBean.rowsPerPage}"
					id="pageField" size="1" style="float: right; positon: relative;">
					<a4j:support event="onkeyup" id="support" requestDelay="500"
						ignoreDupResponses="true"						
						reRender="resultSection, dataResultScroller"						
						oncomplete="#{rich:component('dataResultScroller')}.switchToPage(2); #{rich:component('dataResultScroller')}.switchToPage(1);Richfaces.showModalPanel('panelStatusPesquisaRel');"
						 />
				</h:inputText>

Alguém pode me dar uma luz? Pesquisei sobre lazy model, mas não sei se deveria seguir ou não por esse caminho… ou se sei lá, seria mais prático através de expressão não mostrar os valores nulos, se bem que imagino q isso acabaria impedindo a paginação do jeito que ela está.

Obrigada desde já.

Nossa cara… Eu acho melhor você alterar a procedure no banco.
Se não for possivel, remove esses caras da lista :cold_sweat:
Até deve ter como contornar isso mas vai ficar “feio demais”, saca?
Melhor matar o mau pela raiz! :slight_smile:

Bom, a solução seria melhor se utilizasse os recursos do banco de dados. Se isso não for possível, entenda que você precisará fazer algo como:
1 - Manter uma variável acessível ao xhtml que contenha a informação do total de páginas
2 - Manter uma variável acessível ao xhtml que indique qual a página atual
3 - De acordo com a página selecionada, limpar por completo a lista e inserir os elementos referentes àquela página (ex.: se cada página restringe a 10 elementos e você tem 35, nas três primeiras páginas (1, 2 e 3), insere os 10 elementos respectivos (1 a 10, 11 a 20, 21 a 30) e, na última, apenas os faltantes (31 a 35).
Isso evitará que você insira elementos nulos e permitirá um maior controle das ações.

Obrigada pela sugestão, vou tentar.

Resolvi o problema em partes. No fim das contas é uma paginação sob demanda, com Richfaces, sem Hibernate.
Então, vi um exemplo onde estendia um DataModel, aqui: https://developer.jboss.org/thread/6805

A diferença é que como eu já tinha a lista paginada no banco, a questão era como usar o DataModel no meu Bean.

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

import javax.faces.model.DataModel;

public class PagedListDataModel extends DataModel implements Serializable{

private int rowIndex = -1;
private int totalNumRows;
private int pageSize;
private List list;

public PagedListDataModel() {
super();
}

public PagedListDataModel(List list, int totalNumRows, int pageSize) {
super();
setWrappedData(list);
this.totalNumRows = totalNumRows;
this.pageSize = pageSize;
}

public boolean isRowAvailable() {
if(list == null)
return false;

int rowIndex = getRowIndex();
if(rowIndex >=0 && rowIndex < list.size())
return true;
else
return false;
}

public int getRowCount() {
return totalNumRows;
}

public Object getRowData() {
if(list == null)
return null;
else if(!isRowAvailable())
throw new IllegalArgumentException();
else {
int dataIndex = getRowIndex();
return list.get(dataIndex);
}
}

public int getRowIndex() {
return (rowIndex % pageSize);
}

public void setRowIndex(int rowIndex) {
this.rowIndex = rowIndex;
}

public Object getWrappedData() {
return list;
}

public void setWrappedData(Object list) {
this.list = (List) list;
}

}

e no Bean:

public DataModel getDataModel() {
int totalSize = 0;
int rows = rowsPerPage;
int first = 0;

	if (table != null) {
		first = table.getFirst();
		rows = table.getRows();
	}
	
	if (!minhaLista.isEmpty()) {
		first = listaTreinamento.get(0).getId();
		totalSize = minhaLista.get(0).getTotalRegistrosBanco();
		dataModel = new PagedListDataModel(minhaLista, totalSize, rows);
	}
	
	return dataModel;
}

No xhtml, mudei somente uma linha:

<rich:dataTable value="#{meuBean.dataModel}"
.
.
.

Agora, o problema é que depois que eu rodo a paginação e mudo pra outra tela, quando volto pra essa pesquisa a tela está com os últimos registros que paginei… ficou “sujo”.

Estou pesquisando como deixar sempre limpo ao voltar para a tela de pesquisa.