无法将类型“java.lang.String”的属性值转换为所需类型“java.util.Date”

Posted

技术标签:

【中文标题】无法将类型“java.lang.String”的属性值转换为所需类型“java.util.Date”【英文标题】:Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' 【发布时间】:2018-08-21 18:42:34 【问题描述】:

我正在尝试使用 Spring MVC、Java 和 mysql 在我的 web 应用程序中实现完整的日历插件。当我尝试在我的 jsp 中使用“输入类型 = 日期”添加日期时出现此错误:

Field error in object 'event' on field 'endDate': rejected value [2018-03-13]; 
codes [typeMismatch.event.endDate,typeMismatch.endDate,typeMismatch.java.util.Date,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [event.endDate,endDate]; arguments [];
default message [endDate]]; default message [Failed to convert property value of type 'java.lang.String' 
to required type 'java.util.Date' for property 'endDate'; nested exception is org.springframework.core.convert.ConversionFailedException: 
Failed to convert from type java.lang.String to type @org.springframework.format.annotation.DateTimeFormat
java.util.Date for value '2018-03-13'; 
nested exception is java.lang.IllegalArgumentException: Unable to parse '2018-03-13']

在我的控制器类中,我使用 SimpleDateFormat 来格式化我的日期:

@RequestMapping(value = "add", method = RequestMethod.POST)
    public String add(@ModelAttribute("event") Event event,
            HttpServletRequest request,ServletRequestDataBinder binder,
            ModelMap modelMap)
        try
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat ("dd/MM/yyyy");
            event.setStartDate(simpleDateFormat.parse(request.getParameter("startDate")));
            event.setEndDate(simpleDateFormat.parse(request.getParameter("endDate")));

            eventService.create(event);
            return "redirect:../event.html";
        catch (Exception e)
            modelMap.put("event", event);
            return "event/index";
           
    

最后在我的 Jsp 中:

<fieldset>
        <legend>Event Information</legend>
    <s:form method ="post" commandName = "event"
        action="$pageContext.request.contextPath /event/add.html">
        <table>
            <tr>
                <td>Name</td>
                <td><s:input path = "name"/></td>
            </tr>
            <tr>
                <td valign = "top">Description</td>
                <td><s:textarea path = "description" cols = "20" rows = "5" /></td>
            </tr>
            <tr>
                <td>Start Date</td>
                <td><input type = "date" name = "startDate" /></td>
            </tr>
            <tr>
                <td>End Date</td>
                <td><input type = "date" name = "endDate" /></td>
            </tr>
            <tr>
                <td>&nbsp;</td>
                <td><input type = "submit" value = "Save" /></td>
            </tr>
        </table>
    </s:form>
    </fieldset>

这是 DAO 实现:

@Repository("eventDAO")
public class EventDAOImpl implements EventDAO

    @Autowired
    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    @Override
    public List<EventEntity> findAll() 
        List <EventEntity> list = null;
        Session session = null;
        Transaction transaction = null;
        try
            session = sessionFactory.openSession();
            transaction = session .beginTransaction();
            list = session.createQuery("select e.id as id, "
                    + "e.name as title, "
                    + "DATE_FORMAT(e.startDate, '%Y-%m-%d') as start, "
                    + "DATE_FORMAT(e.endDate, '%Y-%m-%d') as end "
                    + "from Event e")
                    .setResultTransformer(
                            Transformers.aliasToBean(EventEntity.class))
                    .list();
            transaction.commit();
        catch(Exception e)
            list = null;
            if(transaction != null)
                transaction.rollback();
            
        finally
            session.close();
        
        return list;
    

在我的实体类中,我将变量保存为日期,所以它是

private Date endDate;

我认为问题在于解析日期,但我不确定!对此问题的任何解释将不胜感激。

【问题讨论】:

【参考方案1】:

@ModelAttribute("event") Event event 将使 Spring 尝试将请求值 2018-03-13 绑定到 Event 类型内的 private Date endDate 字段。不会调用您的转换代码,因为错误发生在调用 add 方法之前。

您需要使用PropertyEditorConverter 定义全局转换逻辑,如here 所述,或使用org.springframework.format.annotation.DateTimeFormat 指定每个日期字段的格式:

@DateTimeFormat(pattern = "yyyy-MM-dd")
// or use @DateTimeFormat(pattern = DateTimeFormat.ISO.DATE)
private Date endDate;

【讨论】:

是否可以将@DateTimeFormat 设为“dd-MM-yyyy”? 是的,来自SimpleDateFormat 的标准模式和占位符适用。您也可以阅读@InitBinder 注释,但我不喜欢这种方法。我个人会使用private LocalDate endDate; 并确保java.time.LocalDate 是从标准支持的格式绑定的。 使用 java.time.localDate 方式,是否需要更改 DAO 类中的任何内容? 您很可能只想用e.startDate 替换DATE_FORMAT(e.startDate, '%Y-%m-%d') as start 并处理Java 中JDBC 返回的java.sql.Timestamp。这个DATE_FORMAT SQL 函数是对 String 的冗余强制转换,只会使事情复杂化。你将如何在 Java 中映射 java.sql.Timestamp 是一个不同的问题,但冗余操作只会导致问题,例如无声的精度损失。 那么我会更改 Controller 类中的 event.setDate 吗?抱歉所有问题,我是新手,只是想弄清楚!【参考方案2】:

request.getParameter("endDate") 返回字符串 "2018-03-13"。您需要在SimpleDateFormat中提供匹配格式

simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
event.setEndDate(simpleDateFormat.parse(request.getParameter("endDate")));

【讨论】:

以上是关于无法将类型“java.lang.String”的属性值转换为所需类型“java.util.Date”的主要内容,如果未能解决你的问题,请参考以下文章

如何修复错误:无法将类型“java.lang.String”的值转换为所需类型“java.lang.Long”;

无法将 java.lang.String 类型的对象转换为 com.example 类型

无法从类型 [java.lang.String] 转换为类型 [java.lang.Long]

无法将类型“java.lang.String”的属性值转换为属性“事务”所需的类型“java.util.List”

无法将类型“java.lang.String”的属性值转换为所需类型“java.util.Date”

无法将 java.lang.String 类型的属性值转换为所需的 java.time.LocalDateTime 类型