JDBC 工具类 Ⅴ
6.工具类封装
6.1 重复部分整合
package util;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 【VIK】数据库基本操作类
* 提供update和query方法
*/
public class BaseDao {
/**
* 通用update方法,用于处理insert, delete, update方法,所需参数是执行的目标SQL语句
* 和对应的SQL语句参数
*
* @param sql String类型的SQL语句
* @param parameters 对应的当前SQL语句的Object类型不定长参数【不定长参数类内是一个数组】
* @return 当前SQL语句执行操作对应数据表的影响行数
*/
public int update(String sql, Object... parameters) {
// 判断用户提供的参数是否合法
if (null == sql) {
throw new IllegalArgumentException("SQL is null");
}
// 1. 准备数据库操作必要变量
int affectedRows = 0;
PreparedStatement statement = null;
// 2. 获取数据库连接对象
Connection connection = JdbcUtil.getConnection();
try {
// 3. 预处理SQL语句,得到PreparedStatement对象
statement = connection.prepareStatement(sql);
// 4. 获取当前SQL语句参数占位符 ? 个数
int parameterCount = statement.getParameterMetaData().getParameterCount();
// 5. 判断用户参数个数和提供的参数数组情况
if (!(0 == parameterCount || null == parameters || parameterCount != parameters.length)) {
for (int i = 0; i < parameterCount; i++) {
// SQL语句参数下标从1开始,数组下标从0来时
statement.setObject(i + 1, parameters[i]);
}
}
affectedRows = statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(connection, statement);
}
return affectedRows;
}
/**
* 通用query方法,用于处理select语句,用户可以提供当前查询对应的具体哪一个数据类型对象。需要告知
* SQL语句和对应参数
*
* @param sql 目前需要进行查询操作的SQL语句
* @param cls 带有泛型,用于约束当前查询的目标数据类型是哪一个,同时提供Class对象,可以利用反射完成对象创建,赋值成
* 员变量操作
* @param parameters 对应当前SQL语句的参数
* @param <T> 自定义泛型占位符
* @return List集合,带有自定义泛型,泛型对应具体数据类型通过Class 参数确定,没有查询到任何数据返回null
*/
public <T> List<T> query(String sql, Class<T> cls, Object... parameters) {
if (null == sql || null == cls) {
throw new IllegalArgumentException("SQL or cls is null");
}
// 1. 准备必要的变量
ResultSet resultSet = null;
PreparedStatement statement = null;
List<T> list = new ArrayList<>();
// 2. 获取数据库连接对象
Connection connection = JdbcUtil.getConnection();
try {
// 3. 预处理SQL语句,得到PreparedStatement对象
statement = connection.prepareStatement(sql);
// 4. 赋值SQL语句参数
int parameterCount = statement.getParameterMetaData().getParameterCount();
if (!(0 == parameterCount || null == parameters || parameterCount != parameters.length)) {
for (int i = 0; i < parameters.length; i++) {
statement.setObject(i + 1, parameters[i]);
}
}
// 5. 执行SQL语句。得到结果集对象
resultSet = statement.executeQuery();
// 6. 通过while循环逐行解析ResultSet结果集
// 结果集元数据对象
ResultSetMetaData metaData = resultSet.getMetaData();
// 通过结果集元数据对象,得到当前字段列数
int columnCount = metaData.getColumnCount();
while (resultSet.next()) {
// 进入解析过程,证明存在一个对应数据对象
T t = cls.getConstructor().newInstance();
// for i 循环执行完毕,完整解析数据行内容赋值到当前 T 对象中
for (int i = 1; i <= columnCount; i++) {
// 根据列数获取对应的字段,同时字段名也是成员变量名
String fieldName = metaData.getColumnName(i);
// 获取对应字段名称的数据
Object value = resultSet.getObject(fieldName);
// 使用BeanUtils工具,给予指定符合JavaBean规范类对象,指定成员变量名字赋值对应数据。
BeanUtils.setProperty(t, fieldName, value);
}
// 解析结果存入List集合中
list.add(t);
}
} catch (SQLException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(connection, statement, resultSet);
}
// 如果当前List集合中没有元素,返回null,如果有元素返回当前List集合
return list.size() == 0 ? null : list;
}
}
6.2 封装之后的JdbcUtil 工具类
package util;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* JDBC数据库工具类
* 1. 数据库对象获取功能
* 2. 数据库资源关闭功能
*/
public class JdbcUtil {
/*
准备静态成员变量用于保存数据库连接使用的资源内容
*/
private static String jdbcUrl;
private static String username;
private static String password;
/*
利用静态代码块在类文件加载阶段一定会执行的特征,自动加载当前数据库连接所需驱动
*/
static {
try {
// 读取Properties属性文件内容
Properties properties = new Properties();
// 加载指定路径的Properties文件对应当前Properties类
properties.load(new FileInputStream("./src/db.properties"));
// 通过 Properties 属性类对象根据Key获取对应的值
jdbcUrl = properties.getProperty("jdbcUrl");
username = properties.getProperty("username");
password = properties.getProperty("password");
Class.forName(properties.getProperty("driverClass"));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* JDBC工具类获取数据连接对象方法。如果用户提供的数据库连接信息有误,返回null
*
* @return java.sql.Connection对象,如果信息有误,返回null
*/
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(jdbcUrl, username, password);
} catch (SQLException e) {
// 后期可以使用日志来记录操作错误情况。
e.printStackTrace();
}
return connection;
}
/**
* 对外提供关闭数据库连接对象方法
*
* @param conn java.sql.Connection数据库连接对象
*/
public static void close(Connection conn) {
close(conn, null, null);
}
/**
* 对外提供关闭数据库和数据库表搬运工对象方法
*
* @param conn java.sql.Connection 数据库连接对象
* @param st java.sql.Statement 数据库搬运工对象
*/
public static void close(Connection conn, Statement st) {
close(conn, st, null);
}
/**
* 对外提供关闭数据库,数据库表搬运工对象以及数据库查询结果集对象方法
*
* @param conn java.sql.Connection 数据库连接对象
* @param st java.sql.Statement 数据库搬运工对象
* @param rs java.sql.ResultSet 数据库查询结果集对象
*/
public static void close(Connection conn, Statement st, ResultSet rs) {
try {
close(rs, st, conn);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 类内私有化静态成员方法,用于提供关闭资源的一个能力
*
* @param res AutoCloseable 接口不定长参数,要求传入的是当前数据库操作对应的数据库资源
* @throws Exception AutoCloseable 接口中close方法抛出异常
*/
private static void close(AutoCloseable... res) throws Exception {
for (AutoCloseable re : res) {
if (re != null) {
re.close();
}
}
}
}