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

Spring+MySQL项目datetime字段增改时数据截断异常排查

问题原因分析与解决方案

兄弟,我之前踩过几乎一模一样的坑!结合你的配置细节,这个问题本质是时区不匹配+MySQL 5.7严格模式共同导致的——看起来是空值错误,实际是日期在跨时区转换时出了问题,被MySQL当成无效值截断了。

为什么会出现这个“假空值”错误?

  1. MySQL 5.7的严格模式:MySQL 5.7默认启用了STRICT_TRANS_TABLES严格模式,一旦接收到不符合datetime格式的数值,就会触发Data truncation错误,而不是像旧版本那样自动修正或忽略。
  2. 时区不匹配导致的日期转换异常:你的JVM时区设为Europe/Istanbul,数据库时区是GMT+3,但mysql-connector-java 5.1.x版本不会自动同步这些时区。当Hibernate把Java的Date对象传给JDBC驱动时,驱动没有用正确的时区转换,导致最终传递给MySQL的datetime值变成了无效格式(比如因为夏令时偏移导致的日期范围异常),MySQL直接把这个无效值判定为空字符串,从而抛出你看到的错误。

具体解决方案(按优先级排序)

1. 修正JDBC URL的时区参数(最关键)

对于mysql-connector-java 5.1.x版本,必须在JDBC连接URL中显式指定serverTimezone参数,确保和JVM、数据库的时区一致。两种可选写法:

  • 用JVM设置的时区:
    jdbc:mysql://localhost:3306/your_database?serverTimezone=Europe/Istanbul&useSSL=false
    
  • 直接用数据库的GMT+3时区(注意URL中+要转成%2B):
    jdbc:mysql://localhost:3306/your_database?serverTimezone=GMT%2B3&useSSL=false
    

这个参数会强制JDBC驱动在转换日期时使用指定时区,避免出现无效的datetime值。你之前更新驱动无效,大概率是没加这个参数。

2. 验证并调整MySQL的严格模式(可选)

如果第一步解决不了,可以检查MySQL的sql_mode设置:

  • 登录MySQL执行命令查看当前模式:
    SELECT @@sql_mode;
    
  • 如果结果包含STRICT_TRANS_TABLES或STRICT_ALL_TABLES,可以临时关闭(重启MySQL后失效):
    SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION';
    SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION';
    
    不过不推荐长期关闭严格模式,它是MySQL 5.7的安全默认配置,能避免很多数据不一致问题。

3. 确认Hibernate的日期映射配置

检查你的TicketDTO中日期字段的注解,确保映射正确:

import java.util.Date;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Column;

// ...
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATION_DATE", nullable = false)
private Date createdOn;
// ...

确保@Temporal类型和数据库的datetime字段匹配,同时字段没有被错误设置为nullable = false但实际传递了无效值(不过你说代码里已经赋值了,这个大概率没问题)。


内容的提问来源于stack exchange,提问作者esat akacık

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:03:02