Primefaces数据表丢失数据

时间:2012-11-26 09:08:18

标签: jsf datatable primefaces lazy-loading

我在使用PrimeFaces 3.4.1和JSF 2.1.6的dataTable时遇到以下问题。第一次加载页面时,dataTable会填充来自我们数据库的数据,但只要在页面上执行操作(编辑链接,dataTable排序或过滤),dataTable就会丢失其数据。 DataTable包含此类中的元素:

package es.cne.sicbios.entities.tramites.envios;

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

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataContactoEconomico;
import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataEmpresaFilial;
import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataHistoricoTipoSujeto;
import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataPersonaContacto;
import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataPlantaProduccion;
import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataRepresentante;
import es.cne.sicbios.entities.tramites.envios.sujeto.data.EnvioDataSujeto;
import es.cne.sicbios.entities.tramites.solicitudes.SolicitudSujeto;

@SuppressWarnings("serial")
@Entity
public class EnvioSujeto extends Envio implements Serializable{

@ManyToOne(optional = false, cascade = CascadeType.ALL)
private SolicitudSujeto solicitud;

@OneToOne(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private EnvioDataContactoEconomico envioDataContactoEconomico;

@OneToMany(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private List<EnvioDataEmpresaFilial> enviosDataEmpresaFilial;

@OneToMany(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private List<EnvioDataHistoricoTipoSujeto> enviosDataHistoricoTipoSujeto;

@OneToMany(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private List<EnvioDataPlantaProduccion> enviosDataPlantaProduccion;

@OneToOne(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private EnvioDataSujeto envioDataSujeto;

@OneToMany(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private List<EnvioDataPersonaContacto> enviosDataPersonaContacto;

@OneToMany(mappedBy = "envioSujeto", cascade = CascadeType.ALL)
private List<EnvioDataRepresentante> enviosDataRepresentante;

public SolicitudSujeto getSolicitud() {
    return solicitud;
}

public void setSolicitud(final SolicitudSujeto solicitud) {
    this.solicitud = solicitud;
}

... //rest of getters and setters
}

在对dataTable执行操作后进行调试时,我们仅将数据保存在envioDatasujeto字段中,元素上的每个其他数据都将丢失。

这是xhtml:

<ui:composition template="/templates/layout.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
    xmlns:blb="http://ecb.bilbomatica.es/components">

    <ui:define name="content">
        <f:loadBundle basename="es.cne.sicbios.gestionsujetos" var="gestionmsg" />
        <h:form id="formulario">
            <p:messages id="messages" showDetail="true" autoUpdate="true"
                closable="true" />

                <p:dataTable var="envioSujeto"
                value="#{listadoEnviosSujetoMB.lazyListaAllEnvios}" 
                paginator="true" rows="10"
                paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
                rowsPerPageTemplate="5,10,15"               
                selectionMode="single"  
                selection="#{listadoEnviosSujetoMB.envioSeleccionado}" 
                id="listaEnviosSujetos" 
                lazy="true">

                <f:facet name="header">  
                    #{gestionmsg.txt_listadoEnviosSujetos} 
                </f:facet>

                <p:column sortBy="#{envioSujeto.envioDataSujeto.datosSujeto.acronimo}" headerText="#{gestionmsg.column_acronimo}"
                    filterBy="#{envioSujeto.envioDataSujeto.datosSujeto.acronimo}">
                    <h:outputText value="#{envioSujeto.envioDataSujeto.datosSujeto.acronimo}" />                    
                </p:column>

                <p:column sortBy="#{envioSujeto.solicitud.id}"
                    headerText="#{gestionmsg.column_id_tramite}"
                    filterBy="#{envioSujeto.solicitud.id}"
                    filterMatchMode="contains">
                    <h:outputText value="#{envioSujeto.solicitud.id}" />                    
                </p:column>

                <p:column sortBy="#{envioSujeto.fechaCreacion.time}"
                    headerText="#{gestionmsg.column_fechaCreacion}"
                    filterBy="#{envioSujeto.fechaCreacion.time}"
                    filterMatchMode="contains">
                    <h:outputText value="#{envioSujeto.fechaCreacion.time}" >
                        <f:convertDateTime pattern="dd/mm/yyyy"/>
                    </h:outputText>
                </p:column>

                <p:column sortBy="#{envioSujeto.tipo}"
                    headerText="#{gestionmsg.column_tipoEnvio}"
                    filterBy="#{envioSujeto.tipo}"
                    filterMatchMode="contains">
                    <h:outputText value="#{envioSujeto.tipo}" />
                </p:column>

                <p:column sortBy="#{envioSujeto.solicitud.estado}"
                    headerText="#{gestionmsg.column_estado}"
                    filterBy="#{envioSujeto.solicitud.estado}"
                    filterMatchMode="contains">
                    <h:outputText value="#{envioSujeto.solicitud.estado}" />
                </p:column>

                <p:column sortBy="#{envioSujeto.idRegistro}"
                    headerText="#{gestionmsg.column_idRegistro}"
                    filterBy="#{envioSujeto.idRegistro}"
                    filterMatchMode="contains">
                    <h:outputText value="#{envioSujeto.idRegistro}" />
                </p:column>

                <p:column sortBy="#{envioSujeto.id}"
                    headerText="id"
                    filterBy="#{envioSujeto.id}"
                    filterMatchMode="contains">
                    <h:outputText value="#{envioSujeto.id}" />
                </p:column>
                <ui:remove>
                <!-- 
                <p:column 
                    headerText="#{gestionmsg.column_bloqueo}"
                    >
                    <h:outputText value="" />
                </p:column>
                 -->
                 </ui:remove>

            </p:dataTable>

            <p:commandLink icon="ui-icon-pencil"
                update=":formulario"
                actionListener="#{listadoEnviosSujetoMB.goToEditarEnvio}"  >    
                <h:outputText value="Editar" />                                         
            </p:commandLink>
        </h:form>
    </ui:define>
</ui:composition>

它的托管bean:

package es.cne.sicbios.managedbean.gestionsujetos;

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

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import es.cne.sicbios.entities.tramites.envios.Envio;
import es.cne.sicbios.services.tramites.envios.IEnvioService;
import es.cne.sicbios.utils.FacesUtils;

@SuppressWarnings("serial")
@ViewScoped
@ManagedBean(name = "listadoEnviosSujetoMB")
public class ListadoEnviosSujetoMB implements Serializable {

@ManagedProperty(value = "#{envioSujetoService}")
private IEnvioService envioService;
private Envio envio;
private List<Envio> listaAllEnvios;
private LazyEnvioSujetoDataModel lazyListaAllEnvios;
private Envio envioSeleccionado;

/**
 * 
 * Getters y Setters
 */
@PostConstruct
public void init(){
    if (lazyListaAllEnvios == null) {
        lazyListaAllEnvios = new LazyEnvioSujetoDataModel(envioService);
    }
}

public void setEnvioService(final IEnvioService envioService) {
    this.envioService = envioService;
}

public Envio getEnvio() {
    return envio;
}

public void setEnvio(final Envio envio) {
    this.envio = envio;
}

public List<Envio> getListaAllEnvios() {
    if (listaAllEnvios == null) {
        listaAllEnvios =  envioService.getAll();
    }
    return listaAllEnvios;
}

public void setListaAllEnvios(final List<Envio> listaAllEnvios) {
    this.listaAllEnvios = listaAllEnvios;
}

public Envio getEnvioSeleccionado() {
    return envioSeleccionado;
}

public void setEnvioSeleccionado(final Envio envioSeleccionado) {
    this.envioSeleccionado = envioSeleccionado;
}

/**
 * Métodos de navegación
 */
public String goToEditarEnvio() {
    FacesUtils.saveObjectInFlashScope("envio", envioSeleccionado);
    return "/pages/gestionsujetos/envio.xhtml?faces-redirect=true";
}

public LazyEnvioSujetoDataModel getLazyListaAllEnvios() {
    return lazyListaAllEnvios;
}

public void setLazyListaAllEnvios(final LazyEnvioSujetoDataModel lazyListaAllEnvios) {
    this.lazyListaAllEnvios = lazyListaAllEnvios;
}
}

另外,我们尝试对数据进行延迟加载,但它不起作用。这是我们使用的数据模型(来自PrimeFaces.org上的Lazy Loading示例的改编类):

package es.cne.sicbios.managedbean.gestionsujetos;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.bean.ViewScoped;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SelectableDataModel;
import org.primefaces.model.SortOrder;

import es.cne.sicbios.entities.tramites.envios.Envio;
import es.cne.sicbios.services.tramites.envios.IEnvioService;

/**
 * Dummy implementation of LazyDataModel that uses a list to mimic a real datasource like a database.
 */
@ViewScoped
public class LazyEnvioSujetoDataModel extends LazyDataModel<Envio> implements Serializable, SelectableDataModel<Envio> {

/**
 * 
 */
private static final long serialVersionUID = 983251078912322527L;
private final List<Envio> datasource;


public List<Envio> getDatasource() {
    return datasource;
}

public LazyEnvioSujetoDataModel(final IEnvioService envioService) {
    this.datasource = envioService.getAll();
}

@Override
public Envio getRowData(final String rowKey) {
    for(final Envio envio : datasource) {
        if(envio.getId().equals(rowKey))
            return envio;
    }

    return null;
}

@Override
public Object getRowKey(final Envio envio) {
    return envio.getId();
}

@Override
public List<Envio> load(final int first, final int pageSize,
        final String sortField, final SortOrder sortOrder, final Map<String,String> filters) {
    final List<Envio> data = new ArrayList<Envio>();

    //filter
    for(final Envio envio : datasource) {
        boolean match = true;

        for(final Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
            try {
                final String filterProperty = it.next();
                final String filterValue = filters.get(filterProperty);
                final String fieldValue = String.valueOf(envio.getClass().getField(filterProperty).get(envio));

                if(filterValue == null || fieldValue.startsWith(filterValue)) {
                    match = true;
                }
                else {
                    match = false;
                    break;
                }
            } catch(final Exception e) {
                match = false;
            }
        }

        if(match) {
            data.add(envio);
        }
    }

    //sort
    //      if(sortField != null) {
    //          Collections.sort(data, new LazySorter(sortField, sortOrder));
    //      }

    //rowCount
    final int dataSize = data.size();
    this.setRowCount(dataSize);

    //paginate
    if(dataSize > pageSize) {
        try {
            return data.subList(first, first + pageSize);
        }
        catch(final IndexOutOfBoundsException e) {
            return data.subList(first, first + (dataSize % pageSize));
        }
    }
    else {
        return data;
    }
}
}

对这个问题有什么想法吗? 提前致谢, Juanjo。

2 个答案:

答案 0 :(得分:3)

团队合作的朋友可以得到这个问题的答案。我们正在使用Spring Tool Suite,有时它正在改变JSF托管bean的保存方法。我们需要在web.xml上有这个:

<context-param>
    <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
</context-param>

答案 1 :(得分:0)

我有同样的问题,在我意识到这是因为我不小心使用

后我修复了它
import javax.faces.bean.ViewScoped;

包而不是

import javax.faces.view.ViewScoped;