H2数据库跨包调用时日期时区异常:读取数据多偏移3小时
解决H2数据库升级后Instant类型读写时区双重转换问题
问题根源
升级H2到2.2.220版本(同步升级Spring 6、Java 17)后,H2对Instant类型的时区处理逻辑发生变化,加上Spring Data JPA默认配置未同步调整,导致保存时将服务器时区(UTC+3)的时间转成UTC(减3小时),读取时又额外执行一次时区转换(再减3小时),最终出现时间偏差。
解决方案
1. 配置H2数据库连接时区
在H2的JDBC连接URL中显式指定时区为UTC,确保H2存储Instant时不做额外时区转换:
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;TIME_ZONE=UTC
2. 统一Spring JPA的时区配置
在application.properties或application.yml中设置Hibernate的JDBC时区为UTC,避免读写时重复转换:
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
3. 显式指定实体类字段的数据库类型
给Instant字段加上@Column注解,指定存储为带时区的时间类型,避免H2用不带时区的TIMESTAMP导致混淆:
@Entity @Data @NoArgsConstructor public class RefreshToken { @NonNull private String token; @NonNull @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE") private Instant expiryDate; }
验证逻辑
调整配置后,Instant.now()生成的UTC时间会直接存储到H2,读取时也会原样返回,不会再出现双重时区转换的问题,测试中的断言就能通过。
内容的提问来源于stack exchange,提问作者Aarne Avialaynen
相关产品推荐
相关产品推荐

