Bootstrap

Java & MySQL-JDBC编程

初始JDBC

首先我们的问题是, 什么是JDBC, JDBC的全称是(Java Data Connectivity, Java数据库连接) 是Java程序与数据库之间的桥梁, 包含了一套Java定义的用于执行SQL语句的接口, 使开发者能够编写数据库的程序. JDBC的主要作用是 : 与数据库建立连接, 发送SQL语句和处理数据库执行结果


其实JDBC就是一套Java提供的编程接口, 然后由不同的数据库厂商去实现这一套接口, 然后把实现好的一套类库打包成文件, 也就是jar包, 作为Java开发人员, 可能每个数据库对数据的操作都是不一样的(编解码), 但是我们并不需要关心内部的实现, 只需要面向接口编程就可以了, 这就提高了程序的扩展力, 降低了程序的耦合度, 这其实也就是接口在开发中最重要的作用, 当我们更换数据库的时候, 代码几乎不需要进行改动, 因为我们是面向接口进行编程的

在这里插入图片描述

JDBC的工作原理

JDBC的基本的工作原理就下面的几个步骤, 我们接下来的分析都是基于下面的基本步骤来处理的

  • 加载驱动 : 可以通过在数据库官网下载文件到本地使用, 也可以通过配置maven
  • 建立连接 : 可以通过DriverManager或者是DataSource来建立连接
  • 执行SQL : 通过静态的执行工具Statement, 或者是预编译的PreparedStatement来执行SQL
  • 处理结果 : 处理结果, 通过结果集收集结果然后收集迭代
  • 关闭资源 : 通过close()方法倒叙关闭开启的资源

初始Maven

Maven入门简介

Maven其实是一种基于项目对象模型的项目管理工具,可以对 Java 项目进行构建、依赖管理等操作, 其实简单点理解就是, 可以理解为一个云的应用商店, 如果没有maven的话, 我们配置JDBC也就需要下载各大服务器厂商的驱动Jar包到本地使用, 如果Jar包的内容过多就不是很方便, 但是通过Maven我们就不需要下载, 通过远程加载maven仓库中的依赖的方式直接使用Jar包, 更加便捷


修改Maven的配置文件

由于我们idea的自带的maven工具的远端仓库是在国外的, 由于国家防火墙等原因, 可能导致我们无法正常访问, 所以我们需要把maven工程的镜像配置到国内的阿里云上(阿里云上有一个原装maven仓库的镜像)


找到maven的默认位置
我们的idea自带的maven工具的位置是在idea安装目录的plugins里面
下面的图片是找到配置文件的完整路径
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意, 上面的setting.xml才是我们的配置文件的本体, 上面的带日期的那个是我们怕修改错误拷贝的副本, 然后在vscode中打开这个文件, 找到<mirrors></mirrors>镜像这个标签, 修改配置文件为下图
在这里插入图片描述
配置文件<mirrors></mirrors>配置到阿里云的代码, 注意一定按照上面的图片完整拷贝

<mirrors>
    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>*</mirrorOf>
      <name>阿⾥云公共仓库</name>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    <mirror>
      <id>central</id>
      <mirrorOf>*</mirrorOf>
      <name>aliyun central</name>
      <url>https://maven.aliyun.com/repository/central</url>
    </mirror>
    <mirror>
      <id>spring</id>
      <mirrorOf>*</mirrorOf>
      <name>aliyun spring</name>
      <url>https://maven.aliyun.com/repository/spring</url>
    </mirror>
    <!-- 加⼊如下mirror节点 使⽤国内阿⾥云仓库镜像 结束-->
  </mirrors>

至此, 我们的maven就成功修改为了国内镜像

在idea中查看当前的maven使用

在这里插入图片描述
在这里插入图片描述
可以看到我们现在的Maven home pathBundled(Maven3)也就是我们的默认节点

在当前Maven工程中加载数据库驱动

完成了上面的操作之后, 我们就可以进行下一步, 在当前的工程中使用远端的maven仓库依赖
创建一个maven工程如下图
在这里插入图片描述
打开当前maven项目的pom.xml的maven配置文件
在这里插入图片描述
上图是没有进行依赖配置的初始代码, 下面是源代码

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mysql_module</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</project>

现在我们添加一个MySQL数据库连接依赖
首先创建一个<dependencies></dependencies>节点
在这里插入图片描述


获取MySQL驱动包
在下面这个网址中找到你所需要的maven依赖
https://mvnrepository.com, 搜索MySQL
在这里插入图片描述
第一个是最新的, 第二个是历史版本, 找到你所需要的即可
在这里插入图片描述
找到一个打开, 复制maven地址到idea配置文件里的<dependencies></dependencies>即可
在这里插入图片描述
复制内容源代码如下

	<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>

如果不报错就证明环境配置成功了, 依赖加载完毕, 配置成功

DriverManager连接方案

这个方案我们不太推荐使用, 因为这种连接的模式就是简单的物理连接, 连接一次直接就关闭不用了, 比较浪费资源


注册一个驱动

public static void main(String[] args) {

        try {
            // 1. 注册一个驱动(其实就是加载导入一个类, 异常我们捕获一下)
            Class.forName("com.mysql.cj.jdbc.Driver");
         
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

我们查看一下Driver就会发现, 里面有一个static代码块
在这里插入图片描述
也就是这个类在进行类加载的时候就会自动注册一个驱动


创建一个连接

利用刚才的DriverManager类创建一个连接即可, URL是链接码, 格式如下

  • jdbc:mysql://服务器地址:端⼝/数据库?参数名=值[&参数名=值]
  • “jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false”;
  • 可以修改的位置我们用加重标记了, 直接参照上面的格式即可

User就是用户名, Password是密码

public static void main(String[] args) {

        try {
            // 1. 注册一个驱动(其实就是加载导入一个类, 异常我们捕获一下)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 创建一个连接(抛出异常捕获一下, URL是连接码, user是用户名, password是密码(不展示))
            String URL = "jdbc:mysql://127.0.0.1:3306/java113mysql?" +
                    "characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";
            String user = "root";
            String password = "*****";//不予展示
            Connection connection = DriverManager.getConnection(URL, user, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

获取一个操作SQL的对象

可以获取一个静态的操作对象Statement(可能发生SQL注入)也可以使用预编译SQL处理对象PreparedStatement

public static void main(String[] args) {

        try {
            // 1. 注册一个驱动(其实就是加载导入一个类, 异常我们捕获一下)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 创建一个连接(抛出异常捕获一下, URL是连接码, user是用户名, password是密码(不展示))
            String URL = "jdbc:mysql://127.0.0.1:3306/java113mysql?" +
                    "characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";
            String user = "root";
            String password = "*****";//不予展示
            Connection connection = DriverManager.getConnection(URL, user, password);
            // 3. 获取一个操作SQL的对象, 可以是静态的Statement, 也可以是预编译PreparedStatement(需要传参, 等会再说)
            Statement statement = connection.createStatement();
            //PreparedStatement preparedStatement = connection.prepareStatement(参数);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

创建SQL查询获取结果集

这一步就没什么可说的了, 就是创建一个SQL语句获取一下结果集(我们这里是静态的获取)

public static void main(String[] args) {

        try {
            // 1. 注册一个驱动(其实就是加载导入一个类, 异常我们捕获一下)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 创建一个连接(抛出异常捕获一下, URL是连接码, user是用户名, password是密码(不展示))
            String URL = "jdbc:mysql://127.0.0.1:3306/java113mysql?" +
                    "characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";
            String user = "root";
            String password = "*****";//不予展示
            Connection connection = DriverManager.getConnection(URL, user, password);
            // 3. 获取一个操作SQL的对象, 可以是静态的Statement, 也可以是预编译PreparedStatement(需要传参, 等会再说)
            Statement statement = connection.createStatement();
            //PreparedStatement preparedStatement = connection.prepareStatement(参数);
            // 4. 定义一个SQL语句用来操作(不建议使用*因为要使用索引, DQL是excuteQuary, DML是excuteUpdate)
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入要查询的员工姓名:");
            String name = sc.nextLine();
            String sql = "select empno, ename, sal from emp where ename = '" + name + "'";
            ResultSet resultSet = statement.executeQuery(sql);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

遍历结果集输出结果

我们输出结果的方式其实是通过类似迭代器的方式的方式进行遍历

/**
 * 这个类主要就是测试DriverManager如何进行JDBC连接的
 */
public class Demo1_DriverManager {
    public static void main(String[] args) {

        try {
            // 1. 注册一个驱动(其实就是加载导入一个类, 异常我们捕获一下)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 创建一个连接(抛出异常捕获一下, URL是连接码, user是用户名, password是密码(不展示))
            String URL = "jdbc:mysql://127.0.0.1:3306/java113mysql?" +
                    "characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";
            String user = "root";
            String password = "*****";//不予展示
            Connection connection = DriverManager.getConnection(URL, user, password);
            // 3. 获取一个操作SQL的对象, 可以是静态的Statement, 也可以是预编译PreparedStatement(需要传参, 等会再说)
            Statement statement = connection.createStatement();
            //PreparedStatement preparedStatement = connection.prepareStatement(参数);
            // 4. 定义一个SQL语句用来操作(不建议使用*因为要使用索引, DQL是excuteQuary, DML是excuteUpdate)
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入要查询的员工姓名:");
            String name = sc.nextLine();
            String sql = "select empno, ename, sal from emp where ename = '" + name + "'";
            ResultSet resultSet = statement.executeQuery(sql);
            // 5. 遍历结果集收集结果(类似迭代器, 下标从1开始)
            while(resultSet.next()){
                int empno = resultSet.getInt(1);
                String ename = resultSet.getString(2);
                double sal = resultSet.getDouble(3);
                //输出一下结果(使用格式化风格)
                System.out.println(MessageFormat.format("员工编号={0}, 员工姓名={1}, 员工薪资={2}", empno, ename, sal));
            }
            // 6. 关闭资源在finally代码块(因为不管如何都会执行到finally)
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

关闭资源以及完整代码

我们需要在finally语句块中关闭资源, 因为不管怎样, finally语句块的内容都会执行到, 但是由于作用域的原因, 我们需要把变量的声明到try-catch块外部, 我们释放资源的方式是按照倒叙释放资源的模式
完整的执行代码如下

import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;

/**
 * 这个类主要就是测试DriverManager如何进行JDBC连接的
 */
public class Demo1_DriverManager {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            // 1. 注册一个驱动(其实就是加载导入一个类, 异常我们捕获一下)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 创建一个连接(抛出异常捕获一下, URL是连接码, user是用户名, password是密码(不展示))
            String URL = "jdbc:mysql://127.0.0.1:3306/java113mysql?" +
                    "characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";
            String user = "root";
            String password = "*****";//不予展示
            connection = DriverManager.getConnection(URL, user, password);
            // 3. 获取一个操作SQL的对象, 可以是静态的Statement, 也可以是预编译PreparedStatement(需要传参, 等会再说)
            statement = connection.createStatement();
            //PreparedStatement preparedStatement = connection.prepareStatement(参数);
            // 4. 定义一个SQL语句用来操作(不建议使用*因为要使用索引, DQL是excuteQuary, DML是excuteUpdate)
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入要查询的员工姓名:");
            String name = sc.nextLine();
            String sql = "select empno, ename, sal from emp where ename = '" + name + "'";
            resultSet = statement.executeQuery(sql);
            // 5. 遍历结果集收集结果(类似迭代器, 下标从1开始)
            while(resultSet.next()){
                int empno = resultSet.getInt(1);
                String ename = resultSet.getString(2);
                double sal = resultSet.getDouble(3);
                //输出一下结果(使用格式化风格)
                System.out.println(MessageFormat.format("员工编号={0}, 员工姓名={1}, 员工薪资={2}", empno, ename, sal));
            }
            // 6. 关闭资源在finally代码块(因为不管如何都会执行到finally)
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //在finally块中倒叙关闭资源(需要判空和抛异常)
            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();
                }
            }
        }
    }
}

执行结果如下
在这里插入图片描述

DriverManager & Statement的弊端分析

DriverManger和DataSource的连接方式分析

上面我们说到了, DriverManager是纯粹的物理连接, 就是连接一次close的时候就关闭, 这样实际上非常的浪费资源, 但是DataSource就完全不一样了, 这个是通过连接池的方式来节约资源, 需要连接的时候从池中拿一个现成的连接直接用, 用完了再放回去就可以了


所以我们在开发里一般都是用的DataSource, 包括一些框架封装的也是DataSource的连接方式

Statement的弊端以及SQL注入现象

SQL注⼊即是指web应⽤程序对⽤⼾输⼊数据的合法性没有判断或过滤不严,攻击者可以在web应
⽤程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现⾮法操
作,以此来实现欺骗数据库服务器执⾏⾮授权的任意查询,从⽽进⼀步得到相应的数据信息。


由于我们的Statement是静态的操作SQL的方式就非常容易发生SQL注入现象
比如看下面的例子

// 我们在输入name的时候, 用输入下面的字符串
String name = "'or/**/1=1#";
String sql = "select empno, ename, sal from emp where ename = '" + name + "'";
// 这样我们字符串拼接之后就是下面的结果
select empno, ename, sql from emp where ename = ''or/**/1=1#';
// 看一下下面的执行结果

在这里插入图片描述
我们居然查出来了用户的信息, 这实际上是非常危险的, 所以为了避免SQL注入现象的发生, 我推荐使用PreparedStatement预编译的SQL处理对象


DataSource连接方案(PreparedStatement优化)

连接到数据库

首先通过MySQL厂商实现的MysqlDataSource进行连接, 连接完毕之后交给DataSource(JDBC层面)

/**
 * 这个类的作用就是测试DataSource是如何进行JDBC数据库连接的(并且使用PreparedStatement优化)
 */
public class Demo2_DataSource {
    public static void main(String[] args) {
        // 1. 首先还是连接数据库
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
        mysqlDataSource.setUser("root");
        mysqlDataSource.setPassword("*******");//不予展示
        // MysqlDataSource是MySQl厂商的实现, 我们Java程序员使用的JDBC层面的东西, 所以要再次交给JDBC
        DataSource dataSource = mysqlDataSource;
    }
}

创建一个连接

这个和上面的那个DriverManager其实是一样的

/**
 * 这个类的作用就是测试DataSource是如何进行JDBC数据库连接的(并且使用PreparedStatement优化)
 */
public class Demo2_DataSource {
    public static void main(String[] args) {
        try {
            // 1. 首先还是连接数据库
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
            mysqlDataSource.setUser("root");
            mysqlDataSource.setPassword("*******");//不予展示
            // MysqlDataSource是MySQl厂商的实现, 我们Java程序员使用的JDBC层面的东西, 所以要再次交给JDBC
            DataSource dataSource = mysqlDataSource;
            // 2. 建立一个连接
            Connection connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

获得预编译操作对象

PreparedStatement构建的时候需要传入一个SQL语句进行预编译, 这也就是为什么说这叫预编译

public class Demo2_DataSource {
    public static void main(String[] args) {
        try {
            // 1. 首先还是连接数据库
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
            mysqlDataSource.setUser("root");
            mysqlDataSource.setPassword("*******");//不予展示
            // MysqlDataSource是MySQl厂商的实现, 我们Java程序员使用的JDBC层面的东西, 所以要再次交给JDBC
            DataSource dataSource = mysqlDataSource;
            // 2. 建立一个连接
            Connection connection = dataSource.getConnection();
            // 3. 获得预编译操作对象(并传入待编译的SQL语句, 不确定的用占位符?填充)
            String sql = "select empno, ename, sal from emp where ename = ?";
            PreparedStatement statement = connection.prepareStatement(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


为什么这个可以解决SQL注入
因为我们下文输入name的时候, 内部会直接把输入的字符串直接当作ename查找, 不会进行拼接

动态构建SQL语句

通过PreparedStatement中的方法动态构建查询语句(下标从1开始)

public class Demo2_DataSource {
    public static void main(String[] args) {
        try {
            // 1. 首先还是连接数据库
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
            mysqlDataSource.setUser("root");
            mysqlDataSource.setPassword("*******");//不予展示
            // MysqlDataSource是MySQl厂商的实现, 我们Java程序员使用的JDBC层面的东西, 所以要再次交给JDBC
            DataSource dataSource = mysqlDataSource;
            // 2. 建立一个连接
            Connection connection = dataSource.getConnection();
            // 3. 获得预编译操作对象(并传入待编译的SQL语句, 不确定的用占位符?填充)
            String sql = "select empno, ename, sal from emp where ename = ?";
            PreparedStatement statement = connection.prepareStatement(sql);
            // 4. 动态构建查询SQL语句(内容填充)
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入查询的员工姓名:");
            String name = sc.nextLine();
            statement.setString(1, name);
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

收集结果并输出

这个就和之前的完全一样了

public class Demo2_DataSource {
    public static void main(String[] args) {
        try {
            // 1. 首先还是连接数据库
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
            mysqlDataSource.setUser("root");
            mysqlDataSource.setPassword("*******");//不予展示
            // MysqlDataSource是MySQl厂商的实现, 我们Java程序员使用的JDBC层面的东西, 所以要再次交给JDBC
            DataSource dataSource = mysqlDataSource;
            // 2. 建立一个连接
            Connection connection = dataSource.getConnection();
            // 3. 获得预编译操作对象(并传入待编译的SQL语句, 不确定的用占位符?填充)
            String sql = "select empno, ename, sal from emp where ename = ?";
            PreparedStatement statement = connection.prepareStatement(sql);
            // 4. 动态构建查询SQL语句(内容填充)
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入查询的员工姓名:");
            String name = sc.nextLine();
            statement.setString(1, name);
            // 5. 执行结果接收结果集(这里的excuteQuery()是不传参的)
            ResultSet resultSet = statement.executeQuery();
            while(resultSet.next()){
                int empno = resultSet.getInt(1);
                String ename = resultSet.getString(2);
                double sal = resultSet.getDouble(3);
                System.out.println(MessageFormat.format("员工编号={0}, 员工姓名={1}. 员工薪资={2}", empno, ename, sal));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } 
    }
}

关闭资源以及完整代码

import com.mysql.cj.jdbc.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Scanner;

/**
 * 这个类的作用就是测试DataSource是如何进行JDBC数据库连接的(并且使用PreparedStatement优化)
 */
public class Demo2_DataSource {
    public static void main(String[] args) {

        DataSource dataSource = null;
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            // 1. 首先还是连接数据库
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
            mysqlDataSource.setUser("root");
            mysqlDataSource.setPassword("*******");//不予展示
            // MysqlDataSource是MySQl厂商的实现, 我们Java程序员使用的JDBC层面的东西, 所以要再次交给JDBC
            dataSource = mysqlDataSource;
            // 2. 建立一个连接
            connection = dataSource.getConnection();
            // 3. 获得预编译操作对象(并传入待编译的SQL语句, 不确定的用占位符?填充)
            String sql = "select empno, ename, sal from emp where ename = ?";
            statement = connection.prepareStatement(sql);
            // 4. 动态构建查询SQL语句(内容填充)
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入查询的员工姓名:");
            String name = sc.nextLine();
            statement.setString(1, name);
            // 5. 执行结果接收结果集(这里的excuteQuery()是不传参的)
            resultSet = statement.executeQuery();
            while(resultSet.next()){
                int empno = resultSet.getInt(1);
                String ename = resultSet.getString(2);
                double sal = resultSet.getDouble(3);
                System.out.println(MessageFormat.format("员工编号={0}, 员工姓名={1}. 员工薪资={2}", empno, ename, sal));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            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();
                }
            }
        }
    }
}

执行结果
在这里插入图片描述

化简方案代码总览

import com.mysql.cj.jdbc.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 我们尝试把之前的建立数据库连接的代码简化一下
 */
public class DataSourceLite {

    /**
     * 首先定义连接所需要的常量
     */
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/java113mysql?characterEncoding" +
            "=utf8&allowPublicKeyRetrieval=true&useSSL=false";

    private static final String USER = "root";

    //不予展示
    private static final String POSSWORD = "*******";

    private static DataSource dataSource;

    /**
     * 在进行类加载的时期就创建一个数据库连接
     */
    static {
        // 创建一个连接(用特定的值)
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setURL(URL);
        mysqlDataSource.setUser(USER);
        mysqlDataSource.setPassword(POSSWORD);
        // 赋值交给JDBC层面的接口
        dataSource = mysqlDataSource;
    }

    /**
     * 获取一个connection(直接把异常抛出来交给调用方处理)
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }


    /**
     * 释放资源的方案(直接在这个方案内部捕获就行了, 没必要进行上抛
     */
    public static void free(Statement statement, Connection connection){
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class Test_DataSourceLite {
    public static void main(String[] args) {
        //由于作用域的问题, 我们的所有代码都需要在外部声明(try-catch)
        Connection connection = null;
        PreparedStatement statement = null;

        try {
            // 1. 直接获取一个connection连接
            connection = DataSourceLite.getConnection();
            // 2. 创造一个预编译的SQL处理器
            String sql = "insert into t_student values (?,?,?,?);";
            statement = connection.prepareStatement(sql);
            // 3. 提示用户输入查询的信息
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入插入的编号:");
            int stuNo = sc.nextInt();
            System.out.println("请输入插入的学生姓名:");
            String stuName = sc.next();
            System.out.println("请输入插入的年龄:");
            int stuAge = sc.nextInt();
            System.out.println("请输入插入的学校编号:");
            int schNo = sc.nextInt();
            // 4. 进行动态的信息填充
            statement.setInt(1, stuNo);
            statement.setString(2, stuName);
            statement.setInt(3, stuAge);
            statement.setInt(4, schNo);
            // 5. 进行excuteUpdate()并收集结果集(返回的是收到影响的行数)
            int affectRow = statement.executeUpdate();
            if(affectRow == 1){
                System.out.println("插入成功...");
            }else{
                System.out.println("插入失败...");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 6. 关闭释放资源
            DataSourceLite.free(statement, connection);
        }
    }
}

执行结果如下
在这里插入图片描述
查询一下现在数据库的记录
在这里插入图片描述

;