FacesException: 当启用选择时,DataModel必须实现org.primefaces.model.SelectableDataModel。

7

我想学习PF,所以首先尝试显示数据表并在行单击时导航到下一页传递参数,但卡在以下错误上。我找到了类似的问题,但还没有解决。希望有人能帮助我。

我收到以下错误:

DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.

Caused by:
javax.faces.FacesException - DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.

我的页面:

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

<h:head>
<title>Primefaces 3.1</title>

</h:head>
<h:body>
    <h:form id="form">          
            <p:dataTable value="#{tableBean.cars}" var="var" rowkey="#{var.model}" 
            selection="#{tableBean.car}" selectionMode="single">
            <p:column>  <f:facet name="header">
                                <h:outputText styleClass="outputText" value="Model"></h:outputText>
                            </f:facet>
                            <h:outputText styleClass="outputText"
                                value="#{var.model}"></h:outputText>
                        </p:column>
                        <p:column>
                            <f:facet name="header">
                                <h:outputText styleClass="outputText" value="Color"></h:outputText>
                            </f:facet>
                            <h:outputText styleClass="outputText"
                                value="#{var.randomColor}"></h:outputText>
                        </p:column></p:dataTable>                               
        </h:form>
</h:body>
</html>

我的Bean类:

@ManagedBean
@ViewScoped
public class TableBean extends ListDataModel<Car> implements SelectableDataModel<Car>{

    private List<Car> cars;
    private Car car;

    public List<Car> getCars() {

        cars = new ArrayList<Car>();
        Car car1 = new Car();
        car1.setModel("BMW");
        car1.setRandomColor("Black");
        cars.add(car1);
        Car car2 = new Car();       
        car2.setModel("Audi");
        car2.setRandomColor("White");
        cars.add(car2);

        return cars;
    }

    public String onRowSelect(){
        System.out.println("Row Click!!!");
        return "otherpage";//Does this nav works???if not how???
    }

    public Car getCar() {
        return car;
    }

    @Override
    public Car getRowData(String pArg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object getRowKey(Car pArg0) {
        // TODO Auto-generated method stub
        return null;
    }   
    }

OtherBean:

public class Car{

    private String model;   
    private String randomColor; 

    public String getRandomColor() {
        return randomColor;
    }
    public void setRandomColor(String pRandomColor) {
        randomColor = pRandomColor;
    }

    public String getModel() {
        return model;
    }
    public void setModel(String pModel) {
        model = pModel;
    }

}
4个回答

28
#{tableBean.cars}必须实现SelectableDataModel接口,如果您在<p:dataTable>上没有指定rowKey属性。但是你已经把它实现在#{tableBean}上了,这不正确。您可以在PrimeFaces展示页面中找到正确的示例。根据展示代码示例,您的TableBean类必须如下所示:
@ManagedBean
@ViewScoped
public class TableBean implements Serializable {

    private List<Car> cars;
    private Car car;
    private CarDataModel carsModel;

    public TableBean() {
        cars = new ArrayList<Car>();
        // Populate cars here and thus NOT in the getter method!
        carsModel = new CarDataModel(cars);
    }

    // ...
}

假设 CarDataModel 是这样的(再次强调,只是从 PrimeFaces 展示代码示例中复制的):

public class CarDataModel extends ListDataModel<Car> implements SelectableDataModel<Car> {  

    public CarDataModel() {
    }

    public CarDataModel(List<Car> data) {
        super(data);
    }

    @Override
    public Car getRowData(String rowKey) {
        List<Car> cars = (List<Car>) getWrappedData();

        for(Car car : cars) {
            if(car.getModel().equals(rowKey))
                return car;
        }

        return null;
    }

    @Override
    public Object getRowKey(Car car) {
        return car.getModel();
    }

}

最后在<p:dataTable>的值中使用#{tableBean.carsModel}代替#{tableBean.cars},就像展示例子中一样。

<p:dataTable value="#{tableBean.carsModel}" var="car" ... />

另一种更简单的方法是在<p:dataTable>上指定rowKey属性。

<p:dataTable value="#{tableBean.cars}" var="car" rowKey="#{car.model}" ... />

这样你就不需要整个 SelectableDataModel。你只需要确保它永远不会是 null 并且在行之间始终是唯一的。也可以参见DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled, but I have already defined rowKey


要么使用复合键,要么创建一个SelectableDataModel - BalusC
4
请注意,即使您定义了rowKey属性(例如未初始化),但如果该属性返回null,则仍可能收到相同的错误提示。 - Marcus Junius Brutus
对于一个唯一的对象标识,rowKey="#{car.hashCode()}" 可以吗?当然,这取决于你的 hashCode()equals() 实现,但如果没有被重写,它对于每个实例都是唯一的。 - opfau
@opfau:哈希码并不代表类实例的身份(多个不同的实例可以具有相同的哈希码,你知道,int在可用值方面有一个硬限制),但equals方法是这样的(而且没有任何地方强制限制)。 - BalusC
实际上,这并不是一个好主意,因为hashCode()的实现取决于JVM。 - opfau
显示剩余3条评论

1

确保在填充数据表格的"值=.."的bean方法中设置rowKey参数。我的返回此错误是因为rowKey为空。


0

您不必在托管bean中实现数据模型,只需在数据表的属性中指定“rowkey”,如下所示:rowkey =“{mbean.atribute1}”
-- 属性1必须在数据表列中显示。

必须


rowkey参数不需要在数据表中显示为列。 - J Slick

0

对于我的项目,使用复合键作为行键(rowkey)是有效的,例如:rowKey="#{course.getCompositeKey()}

由于我没有复合键变量,所以我只需在我的Course类(在您的情况下是Car类)中创建一个。这2个主键都是字符串,所以我只需说this.compositeKey=this.courseNumber+this.product--您只需使用您的Car类中的任何2个主键,而不是courseNumber和product。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接