文章目录
- 初始JDBC
- JDBC的工作原理
- 初始Maven
- Maven入门简介
- 修改Maven的配置文件
- 在idea中查看当前的maven使用
- 在当前Maven工程中加载数据库驱动
- DriverManager连接方案
- 注册一个驱动
- 创建一个连接
- 获取一个操作SQL的对象
- 创建SQL查询获取结果集
- 遍历结果集输出结果
- 关闭资源以及完整代码
- DriverManager & Statement的弊端分析
- DriverManger和DataSource的连接方式分析
- Statement的弊端以及SQL注入现象
- DataSource连接方案(PreparedStatement优化)
- 连接到数据库
- 创建一个连接
- 获得预编译操作对象
- 动态构建SQL语句
- 收集结果并输出
- 关闭资源以及完整代码
- 化简方案代码总览
初始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 path
是Bundled(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);
}
}
}
执行结果如下
查询一下现在数据库的记录