mysql-connector-java 8.0时差问题

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>

 问题:mysql-connector-java8导致java.util.Date时间入库mysql库相差13个小时

 

解决方案1:jdbc配置连接指定时区

#原有配置
#jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8

#指定为东八区(北京时间)
jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=GMT%2B8

#或指定为上海时间
#jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

解决方案2:修改数据库时区(不推荐使用,可能会影响到其他程序)

 

#查询数据库时区
show variables like '%time_zone'

#在my.cnf文件里指定时区,添加下行代码
default-time_zone = '+8:00

 

原因

com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer() throws SQLException {
    ...
    this.session.getProtocol().initServerSession();
    ...
}
 
com.mysql.cj.protocol.a.NativeProtocol.initServerSession() {
    configureTimezone();
    ...
}
 
com.mysql.cj.protocol.a.NativeProtocol.configureTimezone() {
    String configuredTimeZoneOnServer = this.serverSession.getServerVariable("time_zone");
 
    if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {
        configuredTimeZoneOnServer = this.serverSession.getServerVariable("system_time_zone");
    }
 
    String canonicalTimezone = getPropertySet().getStringProperty(PropertyKey.serverTimezone).getValue();
 
    if (configuredTimeZoneOnServer != null) {
        // user can override this with driver properties, so don't detect if that's the case
        if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) {
            try {
                canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor());
            } catch (IllegalArgumentException iae) {
                throw ExceptionFactory.createException(WrongArgumentException.class, iae.getMessage(), getExceptionInterceptor());
            }
        }
    }
 
    if (canonicalTimezone != null && canonicalTimezone.length() > 0) {
        this.serverSession.setServerTimeZone(TimeZone.getTimeZone(canonicalTimezone));
 
        //
        // The Calendar class has the behavior of mapping unknown timezones to 'GMT' instead of throwing an exception, so we must check for this...
        //
        if (!canonicalTimezone.equalsIgnoreCase("GMT") && this.serverSession.getServerTimeZone().getID().equals("GMT")) {
            throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("Connection.9", new Object[] { canonicalTimezone }),
                    getExceptionInterceptor());
        }
    }
 
    this.serverSession.setDefaultTimeZone(this.serverSession.getServerTimeZone());
}

追踪代码可知,当 MySQL 的 time_zone 值为 SYSTEM 时,会取 system_time_zone 值作为协调时区。

重点在这里!若 String configuredTimeZoneOnServer 得到的是 CST 那么 Java 会误以为这是 CST -0500 ,因此 TimeZone.getTimeZone(canonicalTimezone) 会给出错误的时区信息。

本机默认时区是 Asia/Shanghai +0800 ,误认为服务器时区为 CST -0500 ,实际上服务器是 CST +0800 。

Timestamp 被转换为会话时区的时间字符串了。问题到此已然明晰:

JDBC 误认为会话时区在 CST-5
JBDC 把 Timestamp+0 转为 CST-5 的 String-5
MySQL 认为会话时区在 CST+8,将 String-5 转为 Timestamp-13
最终结果相差 13 个小时!如果处在冬令时还会相差 14 个小时。

 

 

 

 

之前用的mysql是5.1.47,一直稳定运行。

某一天升级8.0版本之后,发现数据库datetime类型的字段数据异常。。。 与系统时间相差13小时

 

 

 

"D:\Program Files\Java\jdk-21\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2025.1.2\lib\idea_rt.jar=50688" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath D:\2025小学期java项目\JDBC\target\classes;D:\2025小学期java项目\JDBC\src\main\lib\mysql-connector-java-8.0.18.jar com.itheimajdbc.JDBCDemo Exception in thread "main" java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support. at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:683) at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:230) at com.itheimajdbc.JDBCDemo.main(JDBCDemo.java:19) Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support. at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:85) at com.mysql.cj.util.TimeUtil.getCanonicalTimezone(TimeUtil.java:132) at com.mysql.cj.protocol.a.NativeProtocol.configureTimezone(NativeProtocol.java:2121) at com.mysql.cj.protocol.a.NativeProtocol.initServerSession(NativeProtocol.java:2145) at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:1310) at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:967) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826) ... 6 more 进程已结束,退出代码为 1 出现什么错误了
最新发布
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值