在Java项目中连接MySQL数据库时,经常遇到时间相差8小时的问题。这是由于时区参数配置不当导致的,本文将详细分析问题原因并提供解决方案。
🔍 问题分析
版本变化影响
驱动版本差异:
- 早期SpringBoot版本:使用mysql-connector-java 5.1.x
- SpringBoot 2.1.7+:默认使用mysql-connector-java 8.0.17+
根本原因
MySQL 8.0驱动变化:
- 默认时区改为UTC(全球统一时间)
- 北京时间为UTC+8
- 时区处理逻辑发生变化
🧠 逻辑分析
时间转换过程
- 应用程序:使用东八区时间(UTC+8)
- MySQL驱动:将时间误认为UTC时间
- 数据库存储:按UTC时间存储
- 读取时:再次转换为本地时间(UTC+8)
- 结果:时间多加了8小时
实际时间: 2024-01-01 12:00:00 (UTC+8)
↓ 驱动误解为UTC时间
存储时间: 2024-01-01 12:00:00 (UTC)
↓ 读取时转换为本地时间
显示时间: 2024-01-01 20:00:00 (UTC+8)
✅ 解决方案
方法一:设置serverTimezone参数
在JDBC连接URL中添加时区参数:
# 使用Asia/Shanghai时区
jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=Asia/Shanghai&useSSL=false
# 使用GMT+8时区
jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=GMT%2B8&useSSL=false
方法二:Spring Boot配置
在application.properties
中配置:
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
方法三:MySQL服务器配置
在MySQL配置文件my.cnf
中设置:
[mysqld]
default-time-zone='+08:00'
🔧 常用时区参数
时区参数 | 说明 | 适用场景 |
---|---|---|
Asia/Shanghai | 上海时区 | 中国大陆推荐 |
GMT%2B8 | GMT+8时区 | URL编码格式 |
UTC | 协调世界时 | 国际化应用 |
Asia/Hong_Kong | 香港时区 | 香港地区 |
💡 最佳实践
开发建议
- 统一时区:项目中统一使用一个时区
- 显式配置:明确设置serverTimezone参数
- 测试验证:部署前测试时间显示是否正确
- 文档记录:在项目文档中记录时区配置
代码示例
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai&useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("password");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
return dataSource;
}
}
📚 参考资料
💡 提示:升级MySQL驱动版本时,务必检查时区配置,避免时间显示错误影响业务逻辑。