自定义Lazy Model分页异常求助:首次进入页面分页按钮未启用
自定义Lazy Model分页按钮首次加载未启用问题排查与解决
使用自定义Lazy Model时遇到以下问题:首次进入xhtml页面,分页按钮处于未启用状态;但对案件列排序后,分页功能恢复正常。数据通过原生查询提取,数据本身无问题,不清楚未排序时分页失效的原因,需要解决。
XHTML代码
<p:dataTable var="expediente" value="#{peticionesPendientesBean.lazyModel}" rowKey="#{expediente.mCodExpediente}" sortBy="#{expediente.t1.id_expediente}" sortOrder="UNSORTED" paginator="true" rows="10" styleClass="desplegable" paginatorTemplate="{CurrentPageReport} 0 Seleccionados {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown} " rowsPerPageTemplate="10,20,50,100,200" id="tblPendientes" lazy="true" emptyMessage="#{msg.tbl_noRegist}" currentPageReportTemplate="#{peticionesPendientesBean.lazyModel.rowCount==1? lbl.tb_exp_pag : lbl.tb_exps_pag}"> <p:column headerText="#{lbl.titulo_peticiones_pendientes}" sortBy="#{expediente.id_expediente}" id="codExpediente"> <h:outputText value="#{expediente.getAtributo(nombreAtributos.CODEXPEDIENTE).value} " /> </p:column>
Java代码(LazyModel的load方法)
/** * @param first * @param pageSize * @param sortField * @param sortOrder * @param filters */ @Override public List<Expediente> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) { try { System.out.println("usuario" + user.getCentroDirectivo().getCodCentro()); System.out.println("perfil" + user.getRole()); System.out.println("peticionesPendientes: " + peticionesPendientes); System.out.println("user: " + user); if (sortField == null || sortOrder.equals(SortOrder.UNSORTED)) { sortField = "id_expediente"; sortOrder = SortOrder.DESCENDING; } this.dataSource = this.peticionesPendientes.buscarPendientesNativa(user.getCentroDirectivo().getCodCentro(), user.getRole(), first, pageSize, sortField, sortOrder); System.out.println("datasource" + dataSource.size()); int count = portaFirmaEnvios.buscarPendientesNativaCount(user.getCentroDirectivo().getCodCentro(), user.getRole()); if (count == 0) { this.setRowCount(0); } else { this.setRowCount(count); } } catch (final Exception e) { final FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(Cadenas.EVENT, new FacesMessage(FacesMessage.SEVERITY_ERROR, Presentacion.ERROR_MSG, ERR.getString("error_con_motor"))); dataSource = new ArrayList<Expediente>(); this.setRowCount(dataSource.size()); logger.log(Level.SEVERE, e.getMessage() + e.getCause(), e); } return dataSource; }
问题根源分析
- 初始排序状态冲突:xhtml中
dataTable设置了sortOrder="UNSORTED",但load方法里手动替换了排序规则,PrimeFaces组件初始化时可能因为状态不匹配,导致分页组件未正确识别总记录数,从而禁用按钮。排序操作触发后,组件重新调用load,此时状态同步,分页功能恢复。 - rowCount初始化时机滞后:总记录数仅在
load方法中设置,而组件初始化时可能未及时获取到该值,分页按钮因无法判断总页数而保持禁用。
解决方案
方案1:移除xhtml的初始排序配置
让LazyModel完全控制初始排序逻辑,去掉dataTable上的sortBy和sortOrder属性:
<p:dataTable var="expediente" value="#{peticionesPendientesBean.lazyModel}" rowKey="#{expediente.mCodExpediente}" paginator="true" rows="10" styleClass="desplegable" paginatorTemplate="{CurrentPageReport} 0 Seleccionados {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown} " rowsPerPageTemplate="10,20,50,100,200" id="tblPendientes" lazy="true" emptyMessage="#{msg.tbl_noRegist}" currentPageReportTemplate="#{peticionesPendientesBean.lazyModel.rowCount==1? lbl.tb_exp_pag : lbl.tb_exps_pag}"> <p:column headerText="#{lbl.titulo_peticiones_pendientes}" sortBy="#{expediente.id_expediente}" id="codExpediente"> <h:outputText value="#{expediente.getAtributo(nombreAtributos.CODEXPEDIENTE).value} " /> </p:column>
方案2:提前初始化rowCount
在LazyModel的构造方法中提前获取总记录数并设置,确保组件初始化时就能拿到正确的总页数:
public class CustomLazyModel extends LazyDataModel<Expediente> { private PortaFirmaEnvios portaFirmaEnvios; private User user; public CustomLazyModel(User user, PortaFirmaEnvios portaFirmaEnvios) { this.user = user; this.portaFirmaEnvios = portaFirmaEnvios; // 初始化时获取总记录数 try { int count = portaFirmaEnvios.buscarPendientesNativaCount(user.getCentroDirectivo().getCodCentro(), user.getRole()); this.setRowCount(count); } catch (Exception e) { this.setRowCount(0); // 异常日志记录 } } @Override public List<Expediente> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) { try { if (sortField == null || sortOrder.equals(SortOrder.UNSORTED)) { sortField = "id_expediente"; sortOrder = SortOrder.DESCENDING; } this.dataSource = this.peticionesPendientes.buscarPendientesNativa(user.getCentroDirectivo().getCodCentro(), user.getRole(), first, pageSize, sortField, sortOrder); } catch (final Exception e) { final FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(Cadenas.EVENT, new FacesMessage(FacesMessage.SEVERITY_ERROR, Presentacion.ERROR_MSG, ERR.getString("error_con_motor"))); dataSource = new ArrayList<Expediente>(); this.setRowCount(dataSource.size()); logger.log(Level.SEVERE, e.getMessage() + e.getCause(), e); } return dataSource; } }
方案3:手动触发初始加载
在页面Bean的初始化方法中,手动调用load方法,确保rowCount被提前设置:
@ManagedBean @ViewScoped public class PeticionesPendientesBean { private LazyDataModel<Expediente> lazyModel; @PostConstruct public void init() { lazyModel = new CustomLazyModel(user, portaFirmaEnvios); // 手动触发初始加载,同步状态 lazyModel.load(0, 10, null, SortOrder.UNSORTED, new HashMap<>()); } }
验证要点
- 检查控制台输出的
rowCount值,确认首次加载时总记录数已正确设置。 - 验证
buscarPendientesNativaCount方法返回的总记录数准确,无过滤条件错误。
内容的提问来源于stack exchange,提问作者Liliymas
相关产品推荐
相关产品推荐

