vlambda博客
学习文章列表

java客户端连接mysql报“MySQLNonTransientConnectionException”的错误解决


连接mysql报“com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException”的错误解决

使用jdbc连接mysql数据库,报错com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException。

JDBCTest.java代码为:

public class JDBCTest {
    public static void main(String[] args) throws Exception {
        Connection connection = null;
        PreparedStatement prepareStatement = null;
        ResultSet rs = null;
 
        try {
            // 加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获取连接
            String url = "jdbc:mysql://localhost:3306/demo";
            String user = "root";
            String password = "xxxxxx";
            connection = DriverManager.getConnection(url, user, password);
            // 获取statement,preparedStatement
            String sql = "select * from tb_user where id=?";
            prepareStatement = connection.prepareStatement(sql);
            // 设置参数
            prepareStatement.setLong(1, 1l);
            // 执行查询
            rs = prepareStatement.executeQuery();
            // 处理结果集
            while (rs.next()) {
                System.out.println(rs.getString("userName"));
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
                System.out.println(rs.getDate("birthday"));
            }
        } finally {
            // 关闭连接,释放资源
            if (rs != null) {
                rs.close();
            }
            if (prepareStatement != null) {
                prepareStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}

百度后有人说原因是连接的mysql数据库是8.0版本,而项目使用com.mysql.jdbc.Driver驱动包是5.1版本,将项目驱动版本改成8.0.11可以解决。

于是将com.mysql.jdbc.Driver的版本改为8.0.11,重新执行代码后报错:

Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Thu May 28 10:34:56 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn'set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

看报错信息的意思是`com.mysql.jdbc.Driver'弃用了,新的驱动是com.mysql.cj.jdbc.Driver。同时下一段的信息意思是不建议在没有服务器身份验证的情况下建立SSL连接。根据MySQL 5.5.45+、5.6.26+和5.7.6+的要求,如果没有设置显式选项,则必须在默认情况下建立SSL连接。我们需要通过设置useSSL=false显式地禁用SSL,或者设置useSSL=true并为服务器证书验证提供信任存储。

改下JDBCTest.java:

/**
 * @author Evan
 */
public class JDBCTest {
    public static void main(String[] args) throws Exception {
        Connection connection = null;
        PreparedStatement prepareStatement = null;
        ResultSet rs = null;
 
        try {
            // 加载驱动,改为com.mysql.cj.jdbc.Driver
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 获取连接,设置useSSL=false
            String url = "jdbc:mysql://localhost:3306/ssmdemo?useSSL=false";
            String user = "root";
            String password = "123456";
            connection = DriverManager.getConnection(url, user, password);
            // 获取statement,preparedStatement
            String sql = "select * from tb_user where id=?";
            prepareStatement = connection.prepareStatement(sql);
            // 设置参数
            prepareStatement.setLong(1, 1l);
            // 执行查询
            rs = prepareStatement.executeQuery();
            // 处理结果集
            while (rs.next()) {
                System.out.println(rs.getString("userName"));
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
                System.out.println(rs.getDate("birthday"));
            }
        } finally {
            // 关闭连接,释放资源
            if (rs != null) {
                rs.close();
            }
            if (prepareStatement != null) {
                prepareStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}

改了之后,继续执行JDBCTest.java,报错......

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.

这个错误是时区问题,数据库安装时默认为英语,0:00时区,Windows系统中,XP的时区是GMT,而Win7的时区是UTC。mysql返回的时间会比实际时间要早8小时。上面的提示信息很明显,我们可以通过配置服务器或者通过serverTimeZone配置Jdbc driver连接参数来指定一个特定的时区。

(1)配置JDBC连接参数。在url连接字符串后面加上?serverTimezone=UTC。

改动后的JDBCTest.java:

/**
 * @author Evan
 */
public class JDBCTest {
    public static void main(String[] args) throws Exception {
        Connection connection = null;
        PreparedStatement prepareStatement = null;
        ResultSet rs = null;
 
        try {
            // 加载驱动,改为com.mysql.cj.jdbc.Driver
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 获取连接,设置useSSL=false,serverTimezone=UTC
            String url = "jdbc:mysql://localhost:3306/ssmdemo?useSSL=false&serverTimezone=UTC";
            String user = "root";
            String password = "123456";
            connection = DriverManager.getConnection(url, user, password);
            // 获取statement,preparedStatement
            String sql = "select * from tb_user where id=?";
            prepareStatement = connection.prepareStatement(sql);
            // 设置参数
            prepareStatement.setLong(1, 1l);
            // 执行查询
            rs = prepareStatement.executeQuery();
            // 处理结果集
            while (rs.next()) {
                System.out.println(rs.getString("userName"));
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
                System.out.println(rs.getDate("birthday"));
            }
        } finally {
            // 关闭连接,释放资源
            if (rs != null) {
                rs.close();
            }
            if (prepareStatement != null) {
                prepareStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}

(2)修改MySQL数据库配置。

show variables like '%time_zone%';

mysql> show variables like "%time_zone%";
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | SYSTEM |
+------------------+--------+

--设置为东八区(北京时间)
set global time_zone='+8:00';

mysql> set global time_zone='+8:00';
Query OK, 0 rows affected (0.00 sec)

设置完重新打开命令行,进入mysql,查询time。

mysql> show variables like "%time_zone%";
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone |        |
| time_zone        | +08:00 |
+------------------+--------+
2 rows in set, 1 warning (0.01 sec)

这时候即使jdbc不加serverTimezone=UTC,依然运行正常。


点个“赞 or 在看” 你最好看!

关注我,和我一起拯救吧


👇典典下面的小咔片给作者鼓励下吧,谢谢老板!!!