Spring Boot不同版本写入ZonedDateTime到MySQL 8的时间差异问题
问题描述
使用Spring Boot 3.0将ZonedDateTime写入MySQL 8时,结果与Spring Boot 3.1/3.2存在差异。本地机器时间为2024-02-22 21:00:00+08:00,Spring Boot 3.0写入的时间为2024-02-22 21:00:00,而3.1/3.2版本写入的是2024-02-22 13:00:00。除Spring Boot版本外,所有代码均一致,请问为何会出现该差异?
相关代码
数据库表创建语句
CREATE TABLE Abc ( id int NOT NULL AUTO_INCREMENT, dt datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
实体类代码
@Data @Entity @Table(name = "Abc") public class Abc { @Id @GeneratedValue(strategy= GenerationType.AUTO) private Integer id; private ZonedDateTime dt; }
Repository接口代码
public interface AbcRepository extends CrudRepository<Abc, Integer> { }
保存数据的代码
Abc abc = new Abc(); abc.setDt(ZonedDateTime.now()); abcRepository.save(abc);
原因分析
- Hibernate版本升级带来的时区转换逻辑变更:Spring Boot 3.0对应Hibernate 6.1.x,Spring Boot 3.1/3.2升级到了Hibernate 6.2.x。Hibernate 6.1默认将
ZonedDateTime转换为数据库服务器的本地时区后存储;而Hibernate 6.2调整了默认行为,会将ZonedDateTime转换为UTC时区再写入datetime字段,这就导致东八区的21:00被转换为UTC的13:00存储。 - JDBC驱动默认配置的调整:Spring Boot 3.1+对MySQL JDBC驱动的默认时区处理做了优化,当未显式指定
serverTimezone参数时,ORM框架会优先采用UTC时区进行时间转换,而3.0版本则会沿用应用或数据库的本地时区。 - MySQL
datetime类型的特性限制:MySQL的datetime类型本身不存储时区信息,仅保存日期时间数值。不同版本的ORM框架对带时区的Java时间类型(如ZonedDateTime)的转换规则差异,直接导致了最终存储结果的不同。
内容的提问来源于stack exchange,提问作者吳俊霆
相关产品推荐
相关产品推荐

