JDBC 工具类 - 05

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();
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值