求助:JSF中无法将用户输入的日期时间转换为Timestamp
这个报错的核心原因很明确:<f:convertDateTime> 默认会将用户输入的日期字符串转换为 java.util.Date 类型,但你的实体类属性 datum 是 java.sql.Timestamp 类型,JSF容器无法自动完成这两种类型的直接转换,因此抛出类型不匹配的异常。
下面给你几种可行的解决方案,按推荐程度排序:
方案1:将实体类属性改为java.util.Date(推荐)
如果你的持久层用的是JPA(比如Hibernate),其实不需要在实体类中直接使用java.sql.Timestamp。JPA会自动将java.util.Date映射到数据库的TIMESTAMP字段,只要你在实体属性上标注正确的注解:
import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity public class Event { // 其他属性... @Temporal(TemporalType.TIMESTAMP) @Column(name = "datum") private Date datum; // getter和setter... }
这种方式最省心,不需要额外的转换器,JSF的默认DateTimeConverter就能直接工作,JPA会帮你处理和数据库的类型映射。
方案2:自定义JSF转换器直接转换为java.sql.Timestamp
如果你必须保留实体类中的java.sql.Timestamp类型,可以自定义一个转换器来替代默认的DateTimeConverter:
步骤1:实现自定义转换器类
import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.FacesConverter; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @FacesConverter("timestampConverter") public class TimestampConverter implements Converter { private static final String PATTERN = "dd.MM.yyyy HH:mm"; // 注意:HH是24小时制,hh是12小时制,根据你的需求调整 @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value == null || value.trim().isEmpty()) { return null; } try { SimpleDateFormat sdf = new SimpleDateFormat(PATTERN); Date utilDate = sdf.parse(value); return new Timestamp(utilDate.getTime()); } catch (ParseException e) { throw new IllegalArgumentException("Invalid date format. Please use " + PATTERN, e); } } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { if (value == null) { return ""; } if (value instanceof Timestamp) { SimpleDateFormat sdf = new SimpleDateFormat(PATTERN); return sdf.format((Timestamp) value); } else { throw new IllegalArgumentException("Value must be a java.sql.Timestamp"); } } }
步骤2:在JSF组件中使用自定义转换器
替换原来的<f:convertDateTime>,改用自定义的转换器:
<h:inputText value="#{eventMB.eventTo.datum}"> <f:converter converterId="timestampConverter" /> </h:inputText>
方案3:在ManagedBean的setter方法中手动转换
这种方式比较取巧,适合快速临时解决问题:
在你的EventMB中,给eventTo的datum属性添加一个额外的setter,接受java.util.Date类型,然后手动转成Timestamp:
public class EventMB { private Event eventTo; // 原有的getter和setter... // 新增一个接受Date类型的setter,供JSF调用 public void setDatum(Date date) { if (date != null) { eventTo.setDatum(new Timestamp(date.getTime())); } else { eventTo.setDatum(null); } } }
然后JSF页面中的代码可以保留原来的<f:convertDateTime>,因为现在setter接受的是Date类型了。
最后提醒一下:注意日期格式中的小时部分,hh是12小时制(需要配合AM/PM),如果你的输入是24小时制的时间,一定要改成HH,否则会出现转换错误。
内容的提问来源于stack exchange,提问作者Rugo

