getRowData和getRowKey从未执行过LazyDataModel

时间:2019-03-04 12:20:07

标签: jsf primefaces

我尝试了很多事情。该线程与另一个线程相关,但是现在问题更具体了。我发现方法getRowData()以及我实现的方法getRowKey()都不会被调用。

我尝试过的事情:

在我的.xhtml文件中,设置rowKey很好。没有编译器错误。在控制器中,写下getRowData()。我尝试选择某些内容,这会破坏整个页面。设置器不会被呼叫。如果我不覆盖getRowData(),编译器仍然可以工作。

当我尝试在Controller中实现getRowKey()getRowData()时,它会告诉我... exception [getRowKey(T object) must be implemented by ...

然后我尝试实现SelectableDataModel,以查看是否有区别,但没有区别。

当我删除selectionMode时,整个选择都很好。分页效果很好。编辑列也可以。但是删除条目所需的contextMenu不起作用。

xhtml:

<h:form id="eintraegeList">
        <p:panel header="Liste aller Einträge">

            <p:dataTable id="table"
                         var="telefonbuch" 
                         lazy="true" 
                         widgetVar="tableWv" 
                         value="#{telefonbuchList.lazyModel}" 
                         editable="true" 
                         resizableColumns="true" 
                         liveResize="true" 
                         style="margin-bottom:20px" 
                         paginator="true" 
                         rows="#{telefonbuchList.pageSize}" 
                         emptyMessage="Keine Telefonbucheinträge vorhanden" 
                         selectionMode="single"
                         selection="#{telefonbuchList.selectedEntry}" 
                         rowKey="#{telefonbuch.id}"
                         currentPageReportTemplate="{startRecord}-{endRecord} von {totalRecords}"
                         paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
                         rowsPerPageTemplate="5,8,10">

            <f:facet name="header">
                <p:commandButton id="toggler" type="button" value="Anzeige" style="float:right" icon="pi pi-align-justify" />
                <p:columnToggler datasource="table" trigger="toggler" />    
            </f:facet>

            <p:ajax event="rowEdit" listener="#{telefonbuchList.onRowEdit}" update="table" />
            <p:ajax event="rowEditCancel" listener="#{telefonbuchList.onRowCancel}" update="table" />
            <p:ajax event="cellEdit" listener="#{telefonbuchList.onCellEdit}" update="table" />
            <p:ajax event="rowSelect" listener="#{telefonbuchList.onRowSelect}" update="table" />

            <p:separator />

                <p:column headerText="ID" sortBy="#{telefonbuch.id}">
                    <h:outputText value="#{telefonbuch.id}" />
                </p:column>
                <p:column headerText="Vorname" sortBy="#{telefonbuch.vorname}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.vorname}" /></f:facet>
                        <f:facet name="input"><p:inputText id="vornameInput" value="#{telefonbuch.vorname}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="Nachname" sortBy="#{telefonbuch.nachname}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.nachname}" /></f:facet>
                        <f:facet name="input"><p:inputText id="nachnameInput" value="#{telefonbuch.nachname}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="Telefonnummer" sortBy="#{telefonbuch.telefonnummer}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.telefonnummer}" /></f:facet>
                        <f:facet name="input"><p:inputText id="telefonnummerInput" value="#{telefonbuch.telefonnummer}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                 <p:column headerText="Handynummer" sortBy="#{telefonbuch.handynummer}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.handynummer}" /></f:facet>
                        <f:facet name="input"><p:inputText id="handynummerInput" value="#{telefonbuch.handynummer}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                 <p:column headerText="Geschäftsstelle" sortBy="#{telefonbuch.geschaeftsstelle}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.geschaeftsstelle}" /></f:facet>
                        <f:facet name="input">
                            <p:selectOneMenu value="#{telefonbuch.geschaeftsstelle}" style="width:100%">
                                <f:selectItems value="#{telefonbuchController.geschaeftsstellen}" var="c" itemLabel="#{geschaeftsstelle}" itemValue="#{geschaeftsstelle}"/>
                            </p:selectOneMenu>
                        </f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="Geschlecht" sortBy="#{telefonbuch.gender.shortGender}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.gender.shortGender}" /></f:facet>
                        <f:facet name="input">
                            <p:selectOneMenu id="gender" value="#{telefonbuch.gender}" style="width:100%">
                                <f:selectItem itemLabel="Keine Angabe" itemValue="" />
                                <f:selectItems value="#{telefonbuch.genders}" var="gender" itemLabel="#{gender.shortGender}" itemValue="#{gender}"/>
                            </p:selectOneMenu>
                        </f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column exportable="false" style="width:20px;text-align:center;">
                    <p:rowEditor />
                </p:column>
            </p:dataTable>

            <p:growl id="growl" showDetail="true" for="eintraege-list">
                <p:autoUpdate />
            </p:growl> 

            <p:separator />

            <p:contextMenu for="table">   
                <p:menuitem value="Löschen" update="table" icon="fas fa-eraser" action="#{telefonbuchList.deleteEntry}"/>
                <p:menuitem value="Edit Cell" icon="pi pi-search" onclick="PF('tableWv').showCellEditor();return false;"/>  
            </p:contextMenu>

        </p:panel>
    </h:form>

控制器:

@Scope(value = "session")
@Component(value = "telefonbuchList")
@ELBeanName(value = "telefonbuchList")
@Join(path = "/", to = "/eintraege-liste.jsf")
public class TelefonbuchListController extends LazyDataModel<Telefonbuch> {

    private static final long serialVersionUID = 1L;
    @Autowired
    private TelefonbuchRepository telefonbuchRepository;
    private List<Telefonbuch> selectedEntries;

    private Telefonbuch selectedEntry;

    private LazyDataModel<Telefonbuch> lazyModel;

    private int pageSize = 5;

    public void deleteEntry() {
        telefonbuchRepository.deleteAll(selectedEntries);
        lazyModel.getWrappedData().removeAll(selectedEntries);
        selectedEntries.clear();
    }

    public LazyDataModel<Telefonbuch> getLazyModel() {
        return lazyModel;
    }

    @Override
    public int getPageSize() {
        return pageSize;
    }

    @Override
    public Telefonbuch getRowData(String rowKey) {
        System.out.println("rowKey: " + rowKey);
        List<Telefonbuch> list = getWrappedData();

        for (Telefonbuch telefonbuch : list) {

            if (telefonbuch.getId().toString().equals(rowKey)) {
                return telefonbuch;
            }
        }

        return null;
    }

    @Override
    public Object getRowKey(Telefonbuch telefonbuch) {
        return telefonbuch != null ? telefonbuch.getId() : null;
    }

    public List<Telefonbuch> getSelectedEntries() {
        return selectedEntries;
    }

    public Telefonbuch getSelectedEntry() {
        return selectedEntry;
    }

    @Deferred
    @RequestAction
    @IgnorePostback
    public void loadData() {
        lazyModel = new LazyDataModel<Telefonbuch>() {

            private static final long serialVersionUID = 1L;

            @Override
            public List<Telefonbuch> load(int first, int pageSize, String sortField, SortOrder sortOrder,
                    Map<String, Object> filters) {

                List<Telefonbuch> result = new ArrayList<Telefonbuch>();

                if (first == 0) {
                    if (sortField != null && !sortField.isEmpty()) {
                        if (sortOrder.name().equalsIgnoreCase("ascending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).ascending()))
                                    .getContent();
                        } else if (sortOrder.name().equalsIgnoreCase("descending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).descending()))
                                    .getContent();
                        }

                    } else {
                        result = telefonbuchRepository.findAll(PageRequest.of(first, pageSize)).getContent();
                    }
                } else {
                    first = first / pageSize;
                    if (sortField != null && !sortField.isEmpty()) {
                        if (sortOrder.name().equalsIgnoreCase("ascending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).ascending()))
                                    .getContent();
                        } else if (sortOrder.name().equalsIgnoreCase("descending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).descending()))
                                    .getContent();
                        }
                    } else {
                        result = telefonbuchRepository.findAll(PageRequest.of(first, pageSize)).getContent();
                    }
                }

                return result;
            }
        };

        lazyModel.setRowCount((int) telefonbuchRepository.count()); // Aufruf auslagern, aber bei gemeinsamen Arbeiten kann neue Row hinzukommen
        lazyModel.setPageSize(pageSize);
    }

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

    public void onRowEdit(RowEditEvent event) {
        Object oldValue = event.getObject();
        telefonbuchRepository.save((Telefonbuch) oldValue);
        FacesMessage msg = new FacesMessage("Eintrag geändert",
                ((Telefonbuch) event.getObject()).getVorname() + " " + ((Telefonbuch) event.getObject()).getNachname());
        FacesContext.getCurrentInstance().addMessage("eintraege-list", msg);
    }

    public void onRowSelect(SelectEvent event) {
        FacesMessage msg = new FacesMessage("Eintrag ausgewählt",
                ((Telefonbuch) event.getObject()).getVorname() + " " + ((Telefonbuch) event.getObject()).getNachname());
        FacesContext.getCurrentInstance().addMessage("eintraege-list", msg);
    }

    @Override
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public void setSelectedEntries(List<Telefonbuch> selectedEntries) {
        this.selectedEntries = selectedEntries;
    }

    public void setSelectedEntry(Telefonbuch selectedEntry) {
        this.selectedEntry = selectedEntry;
    }

型号:

@Data
@Entity
public class Telefonbuch {

    public enum Gender {
        MALE("Männlich"), FEMALE("Weiblich");

        private String shortGender;

        private Gender(String shortGender) {
            this.shortGender = shortGender;
        }

        public String getShortGender() {
            return shortGender;
        }
    }

    @Column
    @Enumerated(EnumType.STRING)
    private Gender gender;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String vorname;

    @Column
    private String nachname;

    @Column
    private String telefonnummer;

    @Column
    private String handynummer;

    @Column
    private String geschaeftsstelle;

    protected Telefonbuch() {
    }

    public Telefonbuch(String vorname, String nachname, String telefonnummer, String handynummer) {
        this.vorname = vorname;
        this.nachname = nachname;
        this.telefonnummer = telefonnummer;
        this.handynummer = handynummer;
    }
  • PrimeFaces 6.2版

  • JSF MyFaces版本2.2.12

  • Java 1.8

  • Spring Boot 2.1.3

1 个答案:

答案 0 :(得分:2)

使用您的方法

TelefonbuchListController.loadData() {
    lazyModel = new LazyDataModel<Telefonbuch>() {
     //...
    }

您将创建abstractLazyDataModel的新匿名实例。然后,将其分配给lazyModel字段,该字段随后返回到您的p:dataTable value属性。

显然,它不会覆盖来自getRowKeygetRowData的非有效abstractLazyDataModel方法。

您将必须像这样覆盖它们:

public void loadData() {
    lazyModel = new LazyDataModel<Telefonbuch>() {

        // ...

        @Override
        public Telefonbuch getRowData(String rowKey) {
            // your implementation here
        }

        @Override
        public Object getRowKey(Telefonbuch telefonbuch) {
            // your implementation here
        }

        // ...

}

您在问题中提出的方法getRowKeygetRowData都属于一个LazyDataModel实现,该实现未分配给p:dataTable value属性。因此,两者都不会被调用。如果它是分配给LazyDataModel p:dataTable属性的value,则您的p:dataTable可能看起来像这样:

<p:dataTable id="table"
    var="telefonbuch" 
    lazy="true" 
    widgetVar="tableWv" 
    value="#{telefonbuchList}" 
...