You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Spring Boot实现HTML表单日期时间输入并保存至MySQL数据库

问题分析

你遇到的核心问题是Spring MVC无法自动将表单提交的日期字符串绑定到java.sql.Date类型的字段,报错提示的"Bean property 'date' is not readable or has an invalid getter method"本质上是类型转换失败导致的——表单提交的是字符串,而Spring默认不知道怎么把它转成java.sql.Date。你的临时字符串转sql.Date方法虽然可行,但确实不够优雅,下面给你两个更符合Spring生态的解决方案:


方案一:使用@DateTimeFormat注解配合Java 8日期类型(推荐)

Spring支持直接绑定Java 8的java.time.LocalDate/LocalTime类型,只需要在实体类字段上加上@DateTimeFormat注解指定格式,就能自动完成表单字符串到日期类型的转换,不需要手动写转换方法。

1. 修改实体类Post.java

把java.sql.Date换成LocalDate,LocalTime保留,同时添加@DateTimeFormat注解,还可以通过@PrePersist自动合并日期和时间到数据库的TIMESTAMP字段:

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String user;
    private String text;
    
    // 绑定日期字段,指定表单提交的格式
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate date;
    
    // 绑定时间字段,默认格式支持HH:mm,无需额外指定
    private LocalTime time;
    
    // 数据库存储的合并时间戳
    @Temporal(TemporalType.TIMESTAMP)
    private java.util.Date myDate;

    // 持久化前自动合并date和time到myDate
    @PrePersist
    public void mergeDateTime() {
        if (date != null && time != null) {
            LocalDateTime localDateTime = LocalDateTime.of(date, time);
            this.myDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        }
    }

    // 必须保证getter/setter正确生成,字段名和表单name一致
    public LocalDate getDate() { return date; }
    public void setDate(LocalDate date) { this.date = date; }
    public LocalTime getTime() { return time; }
    public void setTime(LocalTime time) { this.time = time; }
    // 其他getter/setter...
}

2. 保持表单createPost.html不变

表单中的date和time字段的th:field可以直接对应实体类的字段:

<form action="#" th:action="@{/createPost}" th:object="${post}" method="POST">
 <p>Description: <input type="text" th:field="*{text}" /> </p>
 <p>date: <input type="date" th:field="*{date}" /></p>
 <p>time: <input type="time" th:field="*{time}" /></p>
 <p><input class="submitButton" type="submit" value="Submit" /> </p>
</form>

3. 简化控制器PostController.java

不需要手动处理日期转换,Spring会自动完成绑定:

@RequestMapping(value="/createPost", method=RequestMethod.POST)
public String createPost(@ModelAttribute Post post){
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    String currentUser = authentication.getName();
    post.setUser(currentUser);
    // @PrePersist会自动处理日期时间合并
    postRepository.save(post);
    return "redirect:/";
}

方案二:全局配置日期时间转换器

如果你的应用中有很多地方需要处理日期绑定,可以配置一个全局的Converter,这样所有的String到日期类型的转换都会自动生效,不需要每个字段加注解。

1. 编写全局转换器配置类

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        // 转换String到LocalDate
        registry.addConverter(new Converter<String, LocalDate>() {
            @Override
            public LocalDate convert(String source) {
                return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE);
            }
        });
        
        // 如果仍需使用java.sql.Date,添加这个转换器
        registry.addConverter(new Converter<String, java.sql.Date>() {
            @Override
            public java.sql.Date convert(String source) {
                LocalDate localDate = LocalDate.parse(source);
                return java.sql.Date.valueOf(localDate);
            }
        });
        
        // 转换String到LocalTime
        registry.addConverter(new Converter<String, LocalTime>() {
            @Override
            public LocalTime convert(String source) {
                return LocalTime.parse(source, DateTimeFormatter.ISO_LOCAL_TIME);
            }
        });
    }
}

2. 实体类和控制器无需额外修改

实体类可以保留java.sql.Date或者用LocalDate,控制器直接用@ModelAttribute绑定即可,表单也保持原来的样子。


为什么临时方案不够优雅?

  • 手动处理字符串转换需要写重复代码,容易出现格式错误(比如时区、格式不匹配)
  • 直接接收字符串参数然后转换,破坏了@ModelAttribute的封装性,代码不够整洁
  • 没有利用Spring内置的类型转换机制,增加了维护成本

以上两个方案都是Spring官方推荐的方式,既能解决绑定问题,又能让代码更简洁易维护。

内容的提问来源于stack exchange,提问作者Rem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:17:49