com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:异常处理以及java程序与数据库建立连接的流程

使用的 JDBC 是: mysql-connector-java-5.1.36.jar
使用的 mysql 版本是:8.0.12
使用的 java 1.8

一、创建注册驱动以及建立java程序与mysql数据库的连接时出现的问题

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class WrongTest {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try {
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/my_first","root","123456");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

运行后抛出如下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:400)
	at com.mysql.jdbc.Util.getInstance(Util.java:383)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:958)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872)
	at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2326)
	at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2079)
	at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794)
	at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:400)
	at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)
	at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325)
	at java.sql.DriverManager.getConnection(DriverManager.java:664)
	at java.sql.DriverManager.getConnection(DriverManager.java:247)
	at jdbc.WrongTest.main(WrongTest.java:16)
Caused by: java.lang.NullPointerException
	at com.mysql.jdbc.ConnectionImpl.getServerCharset(ConnectionImpl.java:2999)
	at com.mysql.jdbc.MysqlIO.sendConnectionAttributes(MysqlIO.java:1885)
	at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1814)
	at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1207)
	at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2249)
	at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2280)

经过查询发现是JDBC版本与mysql版本不匹配的问题,因此去下载了8.0.20版本的JDBC
下载链接如下:
JDBC 8.0.20
将jar包导入到项目文件中后,重新运行又抛出如下异常:

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.
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.

谷歌翻译如下:
不推荐使用:加载类“ com.mysql.jdbc.Driver”。 新的驱动程序类为“ com.mysql.cj.jdbc.Driver”。 通过SPI自动注册驱动程序,通常不需要手动加载驱动程序类。
java.sql.SQLException:服务器时区值’。无法识别或代表多个时区。 如果要利用时区支持,则必须配置服务器或JDBC驱动程序(通过“ serverTimezone”配置属性)以使用更特定的时区值。

解决方法:
对于注册驱动

//方法一:以上抛出的异常说明8.0版本的JDBC的jar包中的Driver类位置发生变化。应改为
//"com.mysql.cj.jdbc.Driver"
try {
      Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
      e.printStackTrace();
}
//方法二:省略显示注册驱动的步骤,原因在java.sql.DriverManager的文档注释中有写,



在java.sql.DriverManager类中有这样一段文档注释

/**
When the method getConnection is called,  the DriverManager will attempt to  locate a suitable driver from amongst those loaded at  initialization and those loaded explicitly using the same classloader  as the current applet or application.
*/
翻译过来就是:
当调用getConnection()方法时,DriverManager会尝试从初始化时加载的驱动程序与当前小程序或应用程序中相同的类加载器显示加载的驱动程序中找到合适的驱动程序

对于建立java程序与数据库的连接
mysql 8.0 以上版本不需要建立 SSL 连接的,需要显示关闭。同时需要在url中添加时区设置。

try {
     Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/my_first?useSSL=false&serverTimezone=UTC","root","123456");
} catch (SQLException e) {
     e.printStackTrace();
}

到这里问题得以解决。
为了防止中文乱码可以在url中添加"characterEncoding=utf-8"

try {
     Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/my_first?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC","root","123456");
} catch (SQLException e) {
     e.printStackTrace();
}

对于"jdbc:mysql://localhost:3306/my_first"的格式
①mysql伪协议 “jdbc.mysql://”
②需要连接的数据库所在主机名 如果是本机可以写 “localhost"或者"127.0.0.1”,如果是其他的主机就写这个主机的ip地址
③mysql的端口号:默认3306,如果有单独设置端口号以实际为准
④需要连接的数据库的名字 这里是 my_first

二、下面将完整的java程序连接mysql数据库的过程写一遍

环境:
· 使用的mysql 8.0.12
· java 1.8
· JDBC mysql-connector-java-8.0.20.jar

import java.sql.*;

public class JdbcTest{
    public static void main(String[] args) {
    	//写在外面是为了后面资源的关闭
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
        	//注册驱动和建立程序与数据库连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/ceshi?useSSL=false&serverTimezone=UTC","root","123456");
            //实例化statement对象,作为执行sql语句的载体
            statement = connection.createStatement();
            //需要执行的sql语句
            String sql = "select * from student;";
            //通过statement让sql的查询语句执行,executeQuery主要执行DQL语句
            resultSet = statement.executeQuery(sql);
            //查看结果,resultSet.next()查看是否还有下一行数据
            while(resultSet.next()){
            	//获取该行第一个字段信息
                int id = resultSet.getInt(1);
                //获取该行第二个字段信息
                String name = resultSet.getString(2);
                //格式化输出信息,为了看的更清晰,加了换行
                System.out.printf("学号:%s,姓名:%s \n",id,name);
            }
            //executeUpdate()通常用于DDL和DML语句,例如以下
            //String sql1 = "create table department(id int,name varchar(20))";
            //statement.executeUpdate(sql);
            //String sql2 = "insert into department values(1,'信息学院'))";
            //statement.executeUpdate(sql2);
            //String sql3 = "update department set name = '药学院' where id = 1";
            //statement.executeUpdate(sql3);
            //String sql4 = "delete from department where id = 1";
            //statement.executeUpdate(sql4);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
        	//这里涉及到的三个资源需要按照创建资源的逆顺序进行关闭,通常先关闭resultSet,statement,connection,否则可能会出现异常。关闭资源时需做非空判断,否则会出现NullPointException
            if(resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(statement != null){
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

关于以上提到的DQL,DDL和DML

DQL(Data Query Language) : 数据查询语言。关键字:select… from … where
DDL(Data Definition Language) :数据定义语言,mysql中用到的alter,create,drop,涉及定义或修改表的结构,数据类型等时
DML(Data Manipulation Language) : 数据操纵语言,mysql中用到的insert,delete,update,涉及数据的增加,删除和修改

你可能感兴趣的:(java基础篇,JDBC,mysql)