如何在带有转换器的 JSF 视图中使用 java.sql.Timestamp

How to use a java.sql.Timestamp in JSF view with converter

如何在 PrimeFaces <p:calendar> 等 JSF 日期组件中使用类型为 java.sql.Timestamp 的模型 属性?该组件需要一个 java.util.Date 的实例作为其输入,并且它还将 return 相同类型的 java.util.Date

是否可以为这种情况创建一个转换器?如何实现转换器以将 java.sql.Timestamp 转换为 java.util.Date?我想我需要一个带有 getAsObject()getAsString() 的 JSF 转换器,但我不知道应该在哪里进行转换?

实际上在这种情况下我有一个 List<Model> 显示在 <p:dataTable> 中。在每一行中,我可以直接从 table 设置开始日期和结束日期。所以我需要在 save() 过程中直接使用模型 属性 从 table 获取最新/更新的数据。

这是我的模型示例:

public class Model {

    private Timestamp startDate;
    private Timestamp endDate;

    public Timestamp getStartDate() {
        return startDate;
    }

    public void setStartDate(Timestamp startDate) {
        this.startDate = startDate;
    }

    public Timestamp getEndDate() {
        return endDate;
    }

    public void setEndDate(Timestamp endDate) {
        this.endDate = endDate;
    }

}

这是我的 bean 的示例:

public class PageBean {

    private List<Model> listModel;

    public String save() {
        // Process insert / update listModel to database here
        return "next-page"
    }

    public List<Model> getListModel() {
        return listModel;
    }

    public void setListModel(List<Model> listModel) {
        this.listModel = listModel;
    }
}

这是我的 xhtml 示例:

<p:dataTable value="#{pageBean.listModel}" var="model" >
    <p:column headerText="Start Date">
        <p:calendar value="#{model.startDate}" pattern="dd-MMM-yyyy" ></p:calendar>
    </p:column>
    <p:column headerText="End Date">
        <p:calendar value="#{model.endDate}" pattern="dd-MMM-yyyy" ></p:calendar>
    </p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{pageBean.save()}" ajax="false" />

我觉得如果模型属性类型是java.util.Date直接使用模型是可以的,但是我这里得到的是java.sql.Timestamp类型

您可以将时间戳委托给日期,反之亦然。

import java.sql.Timestamp;
import java.util.Date;
...
private Timestamp timestamp;
...
public Timestamp getTimestamp() {
   return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
    this.timestamp = timestamp;
}

public Date getDate() {

     return timestamp == null ? null : new Date(timestamp.getTime());
}

public void setDate(Date date) {
     timestamp = date == null ? null : new Timestamp(date.getTime())
}

JSF:

<p:calendar id="button" value="#{bean.date}" showOn="button" />

首先,您不应该在您的模型中有特定类型的持久层 属性。您的模型应该有一个 java.util.Date 属性。相反,您的持久层应该更改为能够处理 java.util.Date 模型属性。

改为在持久层中进行转换。

preparedStatement.setTimestamp(i, new Timestamp(model.getDate().getTime()));

不需要反过来,因为 java.sql.Timestamp 已经是 java.util.Date 的子类。

最佳做法是创建一个与@BaulusC 提到的持久层类型分离的模型。但我找到了适合我的情况的解决方案(实际上是一个技巧),即使用 java.util.Map 或创建另一个模型来绑定视图,但它需要更多的工作。您需要将地图或模型映射器中的值放入您的实际模型中。

  1. 通过使用 java.util.Map

这是示例 bean:

public class PageBean {

    private List<Model> listModel;
    private List<Map> listMap;

    public String save() {
        // Move the values from listMap to listModel
        listModel = new ArrayList<Model>();
        for (Map map : listMap) {
            Model model = new Model();
            model.setStartDate(new Timestamp(((Date) map.get("startDate")).getTime());
            model.setEndDate(new Timestamp(((Date) map.get("endDate")).getTime());
            listModel.add(model);
        }
        // Process listModel to database ...
        return "next-page"
    }

    public List<Map> getListMap() {
        return listMap;
    }

    public void setListMap(List<Map> listMap) {
        this.listMap = listMap;
    }
}

在 xhtml 页面中,我们使用 listMap 作为 <p:dataTable> 值:

<p:dataTable value="#{pageBean.listMap}" var="map" >
    <p:column headerText="Start Date">
        <p:calendar value="#{map.startDate}" pattern="dd-MMM-yyyy" ></p:calendar>
    </p:column>
    <p:column headerText="End Date">
        <p:calendar value="#{map.endDate}" pattern="dd-MMM-yyyy" ></p:calendar>
    </p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{pageBean.save()}" ajax="false" />
  1. 通过创建另一个模型

与视图绑定的新模型示例:

public class ModelMapper {

    private Date startDate;
    private Date endDate;

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

}

豆中:

public class PageBean {

    private List<Model> listModel;
    private List<ModelMapper> listModelMapper;

    public String save() {
        // Move the values from listModelMapper to listModel
        listModel = new ArrayList<Model>();
        for (ModelMapper modelMapper : listModelBinder) {
            Model model = new Model();
            model.setStartDate(new Timestamp(modelMapper.getStartdate().getTime());
            model.setEndDate(new Timestamp(modelMapper.getEndDate().getTime());
            listModel.add(model);
        }
        // Process listModel to database ...
        return "next-page"
    }

    public List<ModelMapper> getListModelMapper() {
        return listModelMapper;
    }

    public void setListModelMapper(List<ModelMapper> listModelMapper) {
        this.listModelMapper = listModelMapper;
    }
}

在 xhtml 页面中,我们使用 listModelMapper 作为 <p:dataTable> 值:

<p:dataTable value="#{pageBean.listModelMapper}" var="mapper" >
    <p:column headerText="Start Date">
        <p:calendar value="#{mapper.startDate}" pattern="dd-MMM-yyyy" ></p:calendar>
    </p:column>
    <p:column headerText="End Date">
        <p:calendar value="#{mapper.endDate}" pattern="dd-MMM-yyyy" ></p:calendar>
    </p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{pageBean.save()}" ajax="false" />

此解决方法不需要修改实际模型,但我们需要做其他事情以将值移动到实际模型。这对我来说很有用。希望有用。