前言
在前面的篇章中,我使用了 Statement 完成 JDBC 增删改查,而且我们可以发现在代码中,存在代码重复的地方,例如:获取数据库连接、关闭资源。
所以下面我们可以写一个 JDBC工具类,封装 获取数据库连接、关闭资源 这类的通用方法。
案例-JDBC工具类的抽取
1.目标
掌握JDBC工具类的抽取
2.步骤
- 在src目录下,创建配置文件
- 定义JdbcUtils类
- 定义getConnection()方法
- 定义closeAll()方法
3.实现
3.1 创建配置文件,配置文件在resources目录下,并且要将resources目录标记为资源文件的根路径,扩展名是properties
1537261759376配置文件:
jdbc.username=root
jdbc.password=Li********密码**********0
jdbc.url=jdbc:mysql://localhost:3306/testdb?rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
jdbc.driverClass=com.mysql.jdbc.Driver
3.2 工具类实现
3.2.1 创建 JdbcUtils 工具类
image-20210120080002527image-20210120081644762package com.utils;
/**
*
* @Description:JdbcUtils 工具类
* 1.抽取: 复用重复的代码
* 方式: 把重复代码抽取到父类, 把公共代码抽取成方法, 把公共代码抽取到工具类
* 原则: 抽取重复的
* 2.选择把公共代码抽取到工具类
* 找重复的: (1,2 -- 获得连接的方法), (5-- 释放资源的方法)
* 思路:
* 定义一个类
* 在这个类里面定义两个方法
* 3. 工具类优化
* 把四个参数(驱动,路径,用户名,密码)抽取成 jdbc.properties
* 在static{}里面读取jdbc.properties, 给变量赋值
*
* @author Aron.li
* @date 2021/1/20 7:59
*/
public class JdbcUtils {
}
3.2.2 使用 static 静态代码块获取配置文件的相关参数,并且进行驱动注册
image-20210120085146431public class JdbcUtils {
private static String driverClass;
private static String url;
private static String username;
private static String password;
//驱动只需要注册一次,把注册驱动的代码放在静态代码块
static {
//静态代码块就会在类加载的时候执行
try {
//读取jdbc.properties配置文件中的内容
//1. 将配置文件转换成字节输入流,使用类加载器
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//2. 创建一个Properties对象
Properties properties = new Properties();
//3. properties对象加载配置文件
properties.load(is);
//4.调用properties的方法,根据key获取值
username = properties.getProperty("jdbc.username");
password = properties.getProperty("jdbc.password");
url = properties.getProperty("jdbc.url");
driverClass = properties.getProperty("jdbc.driverClass");
//5.注册驱动
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.2.3 编写获取数据库连接的方法
image-20210120082142705/**
* 获得连接
*
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
//2. 获得连接
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}
3.2.4 编写资源关闭的方法
image-20210120082552351/**
* 释放资源
*
* @param resultSet
* @param statement
* @param connection
* @throws SQLException
*/
public static void closeAll(ResultSet resultSet, Statement statement, Connection connection) throws SQLException {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
}
public static void closeAll(Statement statement, Connection connection) throws SQLException {
closeAll(null, statement, connection);
}
3.3 工具类的完成代码
package com.utils;
import org.junit.jupiter.api.Test;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
import java.util.ResourceBundle;
/**
*
* @Description:JdbcUtils 工具类
* 1.抽取: 复用重复的代码
* 方式: 把重复代码抽取到父类, 把公共代码抽取成方法, 把公共代码抽取到工具类
* 原则: 抽取重复的
* 2.选择把公共代码抽取到工具类
* 找重复的: (1,2 -- 获得连接的方法), (5-- 释放资源的方法)
* 思路:
* 定义一个类
* 在这个类里面定义两个方法
* 3. 工具类优化
* 把四个参数(驱动,路径,用户名,密码)抽取成 jdbc.properties
* 在static{}里面读取jdbc.properties, 给变量赋值
*
* @author Aron.li
* @date 2021/1/20 7:59
*/
public class JdbcUtils {
private static String driverClass;
private static String url;
private static String username;
private static String password;
//驱动只需要注册一次,把注册驱动的代码放在静态代码块
static {
//静态代码块就会在类加载的时候执行
try {
//读取jdbc.properties配置文件中的内容
//1. 将配置文件转换成字节输入流,使用类加载器
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//2. 创建一个Properties对象
Properties properties = new Properties();
//3. properties对象加载配置文件
properties.load(is);
//4.调用properties的方法,根据key获取值
username = properties.getProperty("jdbc.username");
password = properties.getProperty("jdbc.password");
url = properties.getProperty("jdbc.url");
driverClass = properties.getProperty("jdbc.driverClass");
//5.注册驱动
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获得连接
*
*/
public static Connection getConnection() {
//2. 获得连接
Connection connection = null;
try {
connection = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage()); // 抛出运行时异常
}
return connection;
}
/**
* 释放资源
*
* @param resultSet
* @param statement
* @param connection
*/
public static void closeAll(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage()); // 抛出运行时异常
}
}
public static void closeAll(Statement statement, Connection connection) throws SQLException {
closeAll(null, statement, connection);
}
@Test
public void test01() throws Exception {
//1. 获取数据库连接
Connection connection = JdbcUtils.getConnection();
System.out.println(connection);
}
}
3.4 测试工具类,执行SQL
image-20210120085420561/**
* 使用 JDBC工具类 完成多条数据的查询
*
* @throws Exception
*/
@Test
public void test07() throws Exception {
//1. 获取连接
Connection conn = JdbcUtils.getConnection();
//5.使用 Statement 完成数据插入
//5.1 创建执行sql语句对象
Statement statement = conn.createStatement(); // 获取 Statement
//5.2 编写SQL语句:多条数据的查询
String sql = " select * from t_user";
ResultSet resultSet = statement.executeQuery(sql);
// 用来保存多个user查询数据
ArrayList<User> users = new ArrayList<>();
while (resultSet.next()) {
//每遍历一次,就是一条数据
User user = new User(
resultSet.getInt("id"),
resultSet.getString("uname"),
resultSet.getString("age"),
resultSet.getString("sex")
);
//将查询的数据加入到 ArrayList 中
users.add(user);
}
// 遍历查询结果
for (User user : users) {
System.out.println(user);
}
//5.释放资源
JdbcUtils.closeAll(resultSet, statement, conn);
}