【问题标题】:Primefaces datatable duplicates data on deletionPrimefaces 数据表在删除时重复数据
【发布时间】:2014-09-17 17:10:55
【问题描述】:

我正在使用休眠 4、spring 4、lucene 3、primefaces 5、java 7。

我有一个数据表,该数据填充在烤豆上,该表的想法是它向我显示一些未分类的单词,并让我对其进行分类。

初始表的示例看起来很正常

1 2 3 4 5

这是我的页面

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>

</h:head>

<h:form id="form">
    <p:growl id="msgs" showDetail="true" life="2000" />

    <p:dataTable id="words" var="word"
        value="#{wordCatalogatorController.unknownWords}" editable="true"
        style="margin-bottom:20px">
        <f:facet name="header">Row Editing</f:facet>

        <p:ajax event="rowEdit"
            listener="#{wordCatalogatorController.onRowEdit}" update=":form:msgs" />
        <p:ajax event="rowEditCancel"
            listener="#{wordCatalogatorController.onRowCancel}" update=":form:msgs" />

        <p:column headerText="Palabra">
            <p:cellEditor>
                <f:facet name="output">
                    <h:outputText value="#{word.word}" />
                </f:facet>
                <f:facet name="input">
                    <h:outputText value="#{word.word}" />
                </f:facet>
            </p:cellEditor>
        </p:column>

        <p:column headerText="Tipo Palabra">
            <p:cellEditor>
                <f:facet name="output">
                    <h:outputText value="#{word.wordType}" />
                </f:facet>
                <f:facet name="input">
                    <h:selectOneMenu value="#{word.wordType}" style="width:100%"
                        converter="#{wordTypeConverter}">
                        <f:selectItems value="#{wordCatalogatorController.wordTypes}"
                            var="man" itemLabel="#{man.wordType}" itemValue="#{man}" />
                    </h:selectOneMenu>
                </f:facet>
            </p:cellEditor>
        </p:column>

        <p:column style="width:32px">
            <p:rowEditor />
        </p:column>
    </p:dataTable>
</h:form>
</html>

这个 bean 是:

@Controller
@Transactional
public class WordCatalogatorController {

    private List<Word> unknownWords = new ArrayList<Word>();

    private List<WordType> wordTypes = new ArrayList<WordType>();

    public WordCatalogatorController(){
        //inicializamos palabras desconocidas y tipos de palabras!
        for(int i = 0 ; i < 6 ; i++){
            unknownWords.add(new Word("" + i));
        }

        for(int i = 0 ; i < 4 ; i++){
            wordTypes.add(new WordType("" + i));
        }

    }

    public void onRowEdit(RowEditEvent event) {
        Word currentWord = (Word) event.getObject();

        unknownWords.remove(currentWord);
    }

    public void onRowCancel(RowEditEvent event) {
        FacesMessage msg = new FacesMessage("Edit Cancelled",
                ((Word) event.getObject()).getWord());
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

    public void onCellEdit(CellEditEvent event) {
        Object oldValue = event.getOldValue();
        Object newValue = event.getNewValue();

        if (newValue != null && !newValue.equals(oldValue)) {
            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }

然后在编辑并保存第一行 (1) 后,数据表将更新为 1 2 2 3 4 5

任何想法都会非常感激!

pojo 类的代码来了

@Entity
@Table(name="Word")
@Indexed
@AnalyzerDef(name = "searchtokenanalyzer",tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
  @TokenFilterDef(factory = StandardFilterFactory.class),
  @TokenFilterDef(factory = LowerCaseFilterFactory.class),
  @TokenFilterDef(factory = StopFilterFactory.class,params = { 
      @Parameter(name = "ignoreCase", value = "true") }) })
      @Analyzer(definition = "searchtokenanalyzer")
public class Word {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long wordId;

    @Column(name="word")
    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
    @Analyzer(definition="searchtokenanalyzer")
    private String word;

    @ManyToMany(mappedBy="words")
    private Collection<Danger> dangers = new ArrayList<Danger>();

    @ManyToMany(mappedBy="words")
    private Collection<Risk> risks = new ArrayList<Risk>();

    @ManyToMany(mappedBy="words")
    private Collection<Control> controls = new ArrayList<Control>();

    @ManyToOne
    @JoinColumn(name = "wordTypeId")  
    private WordType wordType;

    public Word(String word, WordType wordType) {
        super();
        this.word = word;
        this.wordType = wordType;
    }

    public Word(String word) {
        super();
        this.word = word;
    }



    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Word){
            return ((Word)obj).getWord().equalsIgnoreCase(this.getWord());
        }else{
            return false;
        }
    }

    public Word() {
        super();

    }

    public long getWordId() {
        return wordId;
    }

    public void setWordId(long wordId) {
        this.wordId = wordId;
    }



@Entity
@Table(name = "WordType")
@Indexed
public class WordType {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long wordTypeId;

    @Column(name = "wordType")
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    @Analyzer(definition = "searchtokenanalyzer")
    private String wordType;

    @Column(name = "description")
    private String description;

    @OneToMany(mappedBy = "wordType")
    private Set<Word> words;

    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        if (!(obj instanceof WordType)) {
            return false;
        } else {
            WordType extenalWT = (WordType) obj;
            if (this.wordType.equalsIgnoreCase(extenalWT.getWordType())
                    && this.wordTypeId == extenalWT.getWordTypeId()) {
                return true;
            } else {
                return false;
            }
        }
    }

    public WordType() {

    }

    public WordType(String wordType) {
        this.wordType = wordType;
    }

    public long getWordTypeId() {
        return wordTypeId;
    }

    public void setWordTypeId(long wordTypeId) {
        this.wordTypeId = wordTypeId;
    }

    public String getWordType() {
        return wordType;
    }

    public void setWordType(String wordType) {
        this.wordType = wordType;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Set<Word> getWords() {
        return words;
    }

    public void setWords(Set<Word> words) {
        this.words = words;
    }

    @Override
    public String toString() {
        return wordType;
    }

}

【问题讨论】:

  • 是不是和数据表中的item的id有关?
  • 那里有两个嵌套表单(formform2)。看到这个问题:stackoverflow.com/questions/7371903/….
  • 我只是做了一个更简单的测试并更新了代码,但仍然无法正常工作(这一个只有一个表格)。
  • 能否提供 Word 和 WordType 类的代码?
  • 您好,我正在检查,它似乎是一个 primefaces 错误,无论如何代码(我在主帖上更新)=)

标签: ajax jsf jsf-2 primefaces datatables


【解决方案1】:

对于遇到此问题的其他人:

这似乎是 rowEditor 和表格排序之间的问题。在 ajax 标记上拥有正确的更新目标不是问题,因为从技术上删除了该行,但显示却被弄乱了。你可以用一点点讨厌来解决这个问题。您可以在 ajax 标签的 oncomplete 期间强制过滤。这样就可以去掉ghost重复记录了。

<p:ajax event="rowEdit" 
        listener="#{beanName.onRowEdit}" 
        update=":growl :messages :formName:tableId"
        oncomplete="PF('tableWidgetVar').filter();" />

【讨论】:

    【解决方案2】:

    最后最好的解决方案是为数据表实现select事件,在事件中有一个对话框来选择选项,然后刷新表,这就是最终的xhtml

    <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:p="http://primefaces.org/ui">
    
    <h:head>
    
    </h:head>
    
    <h:body>
    
    
        <h:form id="myForm">
            <p:growl id="msgs" showDetail="true" life="2000" />
    
    
            <p:panel header="Sale Item" style="width: 400px;">
    
                <h:panelGrid columns="2" cellpadding="5">
                    <p:outputLabel value="Texto" for="acSimple" />
                    <p:autoComplete id="acSimple"
                        value="#{wordCatalogatorController.texto}"
                        completeMethod="#{wordCatalogatorController.completeText}"
                        binding="#{wordCatalogatorController.autoCompleteText}" />
    
                    <p:commandButton value="Guardar actividad" id="save"
                        update=":myForm:msgs words"
                        binding="#{wordCatalogatorController.saveButton}"
                        actionListener="#{wordCatalogatorController.saveActivity}"
                        styleClass="ui-priority-primary" process="@this" />
                </h:panelGrid>
    
                <p:dataTable id="words" widgetVar="words" var="word"
                    value="#{wordCatalogatorController.unknownWords}" editable="true"
                    style="margin-bottom:20px" rowKey="#{word.word}"
                    selection="#{wordCatalogatorController.selectedWord}"
                    selectionMode="single" editMode="row">
    
                    <p:ajax event="rowSelect"
                        listener="#{wordCatalogatorController.changeClient}"
                        oncomplete="PF('activityDialog').show()"
                        update=":myForm:activityDialog" />
    
                    <f:facet name="header">Edicion de palabras</f:facet>
    
                    <p:column headerText="Palabra">
                        <h:outputText value="#{word.word}" />
                    </p:column>
    
                    <p:column headerText="Edicion">
                        <h:outputText value="Presione para catalogar la palabra" />
                    </p:column>
                </p:dataTable>
    
            </p:panel>
    
    
    
            <p:dialog id="activityDialog" width="500px" height="600px"
                header="Palabra a catalogar: #{wordCatalogatorController.selectedWord.word}"
                widgetVar="activityDialog" modal="true" closable="false">
    
                <h:panelGrid columns="2" cellpadding="5">
    
                    <p:selectOneMenu id="wordTypes"
                        value="#{wordCatalogatorController.selectedWordType}"
                        style="width: 150px;" converter="#{wordTypeConverter}">
                        <p:ajax
                            listener="#{wordCatalogatorController.wordTypeChangeListener}"
                            update=":myForm:words" />
                        <f:selectItem itemLabel="" itemValue="" />
                        <f:selectItems value="#{wordCatalogatorController.wordTypes}" />
                    </p:selectOneMenu>
                </h:panelGrid>
    
            </p:dialog>
        </h:form>
    </h:body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 2011-09-04
      • 1970-01-01
      • 2013-04-15
      • 2014-09-07
      • 2013-05-01
      • 2016-07-25
      • 2011-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多