自定义JDBC连接,以及实现查询数据库内容转Map、集合、JavaBean

自定义JDBC连接,以及实现查询数据库内容转Map、集合、JavaBean

一、自定义JDBC连接
创建util工具包,在util工具包内创建JdbcUtils连接类。
分析:
1.使用JDBC连接数据库需要先准备JdbcUrl,username,password,所以需要预先准备好上述的三个变量,这里需要注意的是,这三个变量使用private static进行修饰

    private static String jdbcUrl;
    private static String user;
    private static String password;

原因为,我们使用JdbcUtils类进行连接时,不希望实例化对象,而直接使用连接方法,所以之后定义的连接方法需要使用static进行修饰,这样上面的三个资源就必须使用static进行修饰

2.上面说到使用JdbcUtils类进行连接时,我们希望直接调用连接方法,那么连接方法使用static修饰即可,但是我们知道在创建JDBC连接时,必须要先加载JDBC连接驱动,所以这里采用了静态代码块的方式进行JDBC连接驱动的类加载。静态代码块修饰的内容在JdbcUtils类加载时执行,这样当后面在使用JdbcUtils中连接方法时,JDBC连接驱动已经加载完成。

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

3.接下来创建JDBC连接方法,在该方法中使用DriverManager驱动管理类进行数据库的连接。

    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(jdbcUrl, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

这里出现了另外一个问题,那就是我们上面准备的JdbcUrl,username,password,并没有值,当然我们也不能直接在JdbcUtils类中对其进行赋值,这样就将该连接方式写死了,以后再用就需要修改代码,这是不合理的,在这里需要引入配置文件,可以将JdbcUrl,username,password的信息保存在配置文件中,然后在JdbcUtils类中读取该配置文件中的内容即可

创建db.properties配置文件,文件内容如下:

#JDBC连接驱动
className=com.mysql.jdbc.Driver
#连接地址
jdbcUrl=jdbc:mysql://localhost:3306/jdbcstudy?useSSL=false
#用户名
user=root
#密码
password=123123

更改上诉静态代码块中的内容,在执行连接方法之前将配置文件中的内容加载到JdbcUtils类中

    static {
        try {
//            利用JdbcUtilsPlus.class对象获取当前类加载器在当前class文件所处项目位置检索指定名称的文件,
//            获取对应文件的InputStream字节输入流对象
            InputStream resourceAsStream = JdbcUtilsPlus.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(resourceAsStream);
            jdbcUrl = properties.getProperty("jdbcUrl");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            Class.forName(properties.getProperty("className"));
        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
        }
    }

4.创建JDBC关闭方法,在执行完JDBC操作后需要关闭相应资源,在这里需要注意先用后关的基本要求

定义关闭方法如下:

    private static void close(AutoCloseable... resources) {
        for (AutoCloseable resource : resources) {
            try {
                if (resource != null) {
                    resource.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

这里使用了不定长参数,因为并不能确定用户打开的资源个数,这里就拿常用的三个资源来说:Connection connection, Statement statement, ResultSet resultSet,数据库连接对象,sql语句执行对象,结果集对象,上面三类均实现了AutoCloseable 接口,所以这里可以使用接口多态。

在给用户提供多种关闭资源的方式

    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        close(resultSet, statement, connection);
    }

    public static void close(Connection connection, Statement statement) {
        close(statement, connection);
    }

    public static void close(Connection connection) {
        close(connection);
    }

这样就完成了JdbcUtils连接工具的创建。

二、自定义BaseDao工具类

/**
 * BaseDao
 * 基础数据库持久化操作类
 * 提供通用的
 * 1.update更新方法
 * 2.query查询套餐方法
 *      2.a.JavaBean规范对象
 *      2.b.键值对Map双边队列
 *      2.c.仅数据模式的Object数组
 * /

代码如下:

package util;

import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * BaseDao
 * 基础数据库持久化操作类
 * 提供通用的
 * 1.update更新方法
 * 2.query查询套餐方法
 *      2.a.JavaBean规范对象
 *      2.b.键值对Map双边队列
 *      2.c.仅数据模式的Object数组
 *
 */
public class BaseDao {

    /**
     * 提供对应的增删改操作
     *
     * @param sql        指定对应功能的Sql语句
     * @param parameters 指定对应的参数列表
     * @return 返回影响的行数
     * @throws SQLException
     */
    public int update(String sql, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
     
        connection = JdbcUtils.getConnection();
        int affectedRows = 0;
        try {
            statement = connection.prepareStatement(sql);
            /**
             * 获取当前数据的元数据
             */
            ParameterMetaData parameterMetaData = statement.getParameterMetaData();
            /**
             * 通过parameterMetaData调用getParameterCount()方法获取Sql语句中的参数个数
             * 问号个数
             */
            int parameterCount = parameterMetaData.getParameterCount();

            if (parameterCount != parameters.length) {
                throw new IllegalArgumentException("Sql语句所需参数不符");
            }
            for (int i = 0; i < parameters.length; i++) {
                statement.setObject(i + 1, parameters[i]);
            }
            affectedRows = statement.executeUpdate();
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement);
        }
        return affectedRows;
    }

    /**
     * 查询一条记录,返回Map<String, Object>类型双边队列
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的ListMap <String, Object>类型双边队列,查询不到返回NULL,不指定查询条件,返回第一条记录
     * @throws SQLException
     */
    public Map<String, Object> queryMap(String sql, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
       
        connection = JdbcUtils.getConnection();

        Map<String, Object> map = new HashMap<>(16);

        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();

//            获取结果集元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
//            解析结果集
            if (resultSet.next()) {
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    map.put(metaData.getColumnName(i), resultSet.getObject(i));
                }
            }
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return map.isEmpty() ? null : map;
    }

    /**
     * 查询多条记录,返回List<Map<String, Object>>类型集合
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的List<Map < String, Object>>类型集合,查询不到返回NULL,不指定查询条件,返回所有记录
     * @throws SQLException
     */
    public List<Map<String, Object>> queryListMap(String sql, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        
        connection = JdbcUtils.getConnection();

        ArrayList<Map<String, Object>> maps = new ArrayList<>();

        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();

//            获取结果集元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
//            解析结果集
            while (resultSet.next()) {
                Map<String, Object> map = new HashMap<>(16);
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    map.put(metaData.getColumnName(i), resultSet.getObject(i));
                }
                maps.add(map);
            }
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return maps.isEmpty() ? null : maps;
    }

    /**
     * 查询多条记录,返回List<Object[]>类型集合
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的List<Object [ ]>类型集合,查询不到返回NULL,不指定查询条件,返回所有记录
     * @throws SQLException
     */
    public List<Object[]> queryArrayList(String sql, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        
        connection = JdbcUtils.getConnection();

        ArrayList<Object[]> list = new ArrayList<>();
        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            while (resultSet.next()) {
                Object[] obj = new Object[metaData.getColumnCount()];
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    obj[i] = resultSet.getObject(i + 1);
                }
                list.add(obj);
            }
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return list.isEmpty() ? null : list;
    }

    /**
     * 查询单条记录,返回Object类型数组
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的Object类型数组,查询不到返回NULL,不指定查询条件,返回第一条记录
     * @throws SQLException
     */
    public Object[] queryArray(String sql, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        
        connection = JdbcUtils.getConnection();

        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            Object[] obj = new Object[metaData.getColumnCount()];
            if (resultSet.next()) {
                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    obj[i] = resultSet.getObject(i + 1);
                }
            }
            return obj;
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
    }


    /**
     * 根据指定的sql查询对应的信息,返回对应的JavaBean规范的数据对象集合
     *
     * @param sql        指定的sql查询信息
     * @param cls        JavaBean规范的对象
     * @param parameters 指定查询参数
     * @param <T>
     * @return 返回对应的JavaBean规范的数据对象集合
     * @throws SQLException
     */
    public <T> List<T> queryListBean(String sql, Class<T> cls, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        
        connection = JdbcUtils.getConnection();
        ArrayList<T> list = new ArrayList<>();
        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();
            Constructor<T> constructor = cls.getConstructor();
            int columnCount = resultSet.getMetaData().getColumnCount();
            while (resultSet.next()) {
                T t = constructor.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    BeanUtils.setProperty(t, resultSet.getMetaData().getColumnName(i), resultSet.getObject(i));
                }
                list.add(t);
            }
        } catch (SQLException e) {
            throw e;
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return list;
    }


    /**
     * 根据指定的sql查询对应的信息,返回对应的JavaBean规范的数据对
     *
     * @param sql        指定的sql查询信息
     * @param cls        JavaBean规范的对象
     * @param parameters 指定查询参数
     * @param <T>
     * @return 返回对应的JavaBean规范的数据对象
     * @throws SQLException
     */
    public <T> T queryBean(String sql, Class<T> cls, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        
        connection = JdbcUtils.getConnection();
        T t = null;
        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();
            Constructor<T> constructor = cls.getConstructor();
            int columnCount = resultSet.getMetaData().getColumnCount();
            if (resultSet.next()) {
                t = constructor.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    BeanUtils.setProperty(t, resultSet.getMetaData().getColumnName(i), resultSet.getObject(i));
                }
            }
        } catch (SQLException e) {
            throw e;
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return t;
    }


    /**
     * 校验输入的Sql语句是否合法
     *
     * @param sql 输入的Sql语句
     */
    private void check(String sql) {
        if (null == sql || sql.isEmpty()) {
            throw new IllegalArgumentException("非法sql语句异常");
        }
    }

    /**
     * 校验传入的参数和Sql语句所需的参数是否符合,不符合抛出非法参数异常
     * 符合将输入的参数列表提交到对那个的sql位置
     *
     * @param statement  PreparedStatement类型的sql语句执行接口
     * @param parameters 用户提供的参数列表
     * @throws SQLException
     */
    private void handlereStatement(PreparedStatement statement, Object[] parameters) throws SQLException {
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        if (parameterMetaData.getParameterCount() != parameters.length) {
            throw new IllegalArgumentException("Sql语句所需参数不符");
        }
        for (int i = 0; i < parameters.length; i++) {
            statement.setObject(i + 1, parameters[i]);
        }
    }
}

从上面的代码可以看出代码非常的冗余,下面让我们采用另外一种方式将其改进。

分析:对上述代码的查询功能进行分析,可知,上面的建立数据库连接,执行sql语句,以及下面关闭资源的操作基本一样,不同点仅仅在于对数据的处理,这样我们可以设计一个接口,接口中只有一个数据处理方法,然后在各个实现类中完成数据的处理。
接口如下:

package util;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 自定义Java.sql.ResultSet数据库查询结果集对象
 *
 */
public interface ResultSetHandler<T> {
    /**
     * 结果集处理器接口
     *
     * @param resultSet 结果集
     * @return 由实现类决定
     * @throws SQLException
     */
    T handler(ResultSet resultSet) throws SQLException;
}

首先设计如下代码:

    /**
     * 通用查询方法
     * 方法所需参数是执行目标的 SQL 语句,对应当前结果集处理方式 ResultSetHandler 接口实现类,
     * 同时利用 ResultSetHandler 类型约束泛型对应具体数据类型,也是同时约束当前方法对应的返回
     * 值类型。方法还需要给予 SQL 语句所需参数列表,返回值类型由 ResultSetHandler 处理器接口
     * 约束。
     *
     * @param sql        目标查询执行的 SQL 语句
     * @param rsh        ResultSetHandler 结果集处理器接口实现类对象,同时约束泛型,也就是约束方法
     *                   返回值类型
     * @param parameters 对应的 SQL 语句的参数列表,为 Object 类型不定长参数
     * @param <T>        自定义泛型占位符,主要约束当前方法的返回值结果
     * @return 根据当前使用的 ResultSetHandler 结果集处理器方式,返回值对应 ResultSet 最终数据
     * 处理结果
     */
    public <T> T query(String sql, ResultSetHandler<T> rsh, Object... parameters) throws SQLException {
        check(sql);
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Connection connection = null;
        FileUtils.addJdbcInformation("D:/JavaSE_Study/MysqlStudy/src/jdbcstudy/path.txt");
        connection = JdbcUtils.getConnection();
        T t = null;
        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();
            t = rsh.handler(resultSet);
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return t;
    }

在来设计实现类,以ListBean为例:

package util.impl;

import org.apache.commons.beanutils.BeanUtils;
import util.ResultSetHandler;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


public class ListBeanHandler<T> implements ResultSetHandler<List<T>> {
    private final Class<T> cls;
    public ListBeanHandler(Class<T> cls) {
        this.cls = cls;
    }

    @Override
    public List<T> handler(ResultSet resultSet) throws SQLException {
        T t = null;
        ArrayList<T> list = null;
        try {
            Constructor<T> constructor = cls.getConstructor();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            list = new ArrayList<>(columnCount);
            while (resultSet.next()) {
                t = constructor.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    BeanUtils.setProperty(t, metaData.getColumnName(i), resultSet.getObject(i));
                }
                list.add(t);
            }
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return list.isEmpty() ? null : list;
    }
}

后面对于不同的方法设计不同的类即可,这里面的BeanUtils.setProperty使用了第三方jar包
在这里插入图片描述
若不想使用,可以使用反射完成上诉操作

package com.test1;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 实现符合 JavaBean 规范实体类
 *
 */
public class BeanUtils {
    /**
     * 用户指定符合 JavaBean 规范的类对象 bean,指定当前类对象中的对应成员变量名称,
     * 给予当前成员变量赋值使用数据 String 类型参数 value,完成赋值操作
     *
     * @param bean      指定的JavaBean规范对象
     * @param fieldName 属性
     * @param value     值
     */
    public static void setProperty(Object bean, String fieldName, String value) {
//        获取该JavaBean对象的Class对象
        Class<?> cls = bean.getClass();
        try {
            Field field = cls.getDeclaredField(fieldName);
            field.setAccessible(true);
            Class<?> type = field.getType();

            if (String.class.equals(type)) {
                field.set(bean, value);
            } else if (Integer.class.equals(type)) {
                field.set(bean, Integer.parseInt(value));
            } else if (Character.class.equals(type)) {
                field.set(bean, value.charAt(0));
            } else {
                Method method = type.getMethod("parse" + type.getName().substring(type.getName().lastIndexOf(".") + 1), String.class);
                field.set(bean, method.invoke(null, value));
            }
        } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取用户指定符合 JavaBean 规范类对象 bean,
     * 指定成员变量名称 fieldName 存储的数据,为保证数据的精确性,返回值类型是 String 类型
     *
     * @param bean      指定的JavaBean规范对象
     * @param fieldName 指定的属性
     * @return 返回该属性对应的值
     */
    public static String getProperty(Object bean, String fieldName) {
        Class<?> cls = bean.getClass();
        Object o = null;
        try {
            Field field = cls.getDeclaredField(fieldName);
            field.setAccessible(true);
            o = field.get(bean);
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }
        return String.valueOf(o);
    }

    public static void populate(Object bean, Map<String, String> map) {
        Class<?> cls = bean.getClass();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            setProperty(bean, entry.getKey(), entry.getValue());
        }
    }

}

这里不再多说

改进完的代码如下:

package util;

import util.impl.*;

import java.sql.*;
import java.util.List;
import java.util.Map;

/**
 * BaseDao
 * 基础数据库持久化操作类
 * 提供通用的
 * 1.update更新方法
 * 2.query查询套餐方法
 * 2.a.JavaBean规范对象
 * 2.b.键值对Map双边队列
 * 2.c.仅数据模式的Object数组
 *
 */
public class BaseDaoPlus {

    /**
     * 提供对应的增删改操作
     *
     * @param sql        指定对应功能的Sql语句
     * @param parameters 指定对应的参数列表
     * @return 返回影响的行数
     * @throws SQLException
     */
    public int update(String sql, Object... parameters) throws SQLException {
        check(sql);
        Connection connection = null;
        PreparedStatement statement = null;
        FileUtils.addJdbcInformation("D:/JavaSE_Study/MysqlStudy/src/jdbcstudy/path.txt");
        connection = JdbcUtils.getConnection();
        int affectedRows = 0;
        try {
            statement = connection.prepareStatement(sql);
            /**
             * 获取当前数据的元数据
             */
            ParameterMetaData parameterMetaData = statement.getParameterMetaData();
            /**
             * 通过parameterMetaData调用getParameterCount()方法获取Sql语句中的参数个数
             * 问号个数
             */
            int parameterCount = parameterMetaData.getParameterCount();

            if (parameterCount != parameters.length) {
                throw new IllegalArgumentException("Sql语句所需参数不符");
            }
            for (int i = 0; i < parameters.length; i++) {
                statement.setObject(i + 1, parameters[i]);
            }
            affectedRows = statement.executeUpdate();
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement);
        }
        return affectedRows;
    }

    /**
     * 查询一条记录,返回Map<String, Object>类型双边队列
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的ListMap <String, Object>类型双边队列,查询不到返回NULL,不指定查询条件,返回第一条记录
     * @throws SQLException
     */
    public Map<String, Object> queryMap(String sql, Object... parameters) throws SQLException {
        return query(sql, new MapHandler(), parameters);
    }

    /**
     * 查询多条记录,返回List<Map<String, Object>>类型集合
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的List<Map < String, Object>>类型集合,查询不到返回NULL,不指定查询条件,返回所有记录
     * @throws SQLException
     */
    public List<Map<String, Object>> queryListMap(String sql, Object... parameters) throws SQLException {
        return query(sql, new MapListHandler(), parameters);
    }

    /**
     * 查询多条记录,返回List<Object[]>类型集合
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的List<Object [ ]>类型集合,查询不到返回NULL,不指定查询条件,返回所有记录
     * @throws SQLException
     */
    public List<Object[]> queryArrayList(String sql, Object... parameters) throws SQLException {
        return query(sql, new ArrayListHandler(), parameters);
    }

    /**
     * 查询单条记录,返回Object类型数组
     *
     * @param sql        指定查询Sql语句
     * @param parameters 指定查询的参数列表
     * @return 返回指定查询条件的Object类型数组,查询不到返回NULL,不指定查询条件,返回第一条记录
     * @throws SQLException
     */
    public Object[] queryArray(String sql, Object... parameters) throws SQLException {
        return query(sql, new ArrayHandler(), parameters);
    }

    /**
     * 根据指定的sql查询对应的信息,返回对应的JavaBean规范的数据对象集合
     *
     * @param sql        指定的sql查询信息
     * @param cls        JavaBean规范的对象
     * @param parameters 指定查询参数
     * @param <T>
     * @return 返回对应的JavaBean规范的数据对象集合
     * @throws SQLException
     */
    public <T> List<T> queryListBean(String sql, Class<T> cls, Object... parameters) throws SQLException {
        return query(sql, new ListBeanHandler<>(cls), parameters);
    }

    /**
     * 根据指定的sql查询对应的信息,返回对应的JavaBean规范的数据对
     *
     * @param sql        指定的sql查询信息
     * @param cls        JavaBean规范的对象
     * @param parameters 指定查询参数
     * @param <T>
     * @return 返回对应的JavaBean规范的数据对象
     * @throws SQLException
     */
    public <T> T queryBean(String sql, Class<T> cls, Object... parameters) throws SQLException {
        return query(sql, new BeanHandler<>(cls), parameters);
    }

    /**
     * 校验输入的Sql语句是否合法
     *
     * @param sql 输入的Sql语句
     */
    private void check(String sql) {
        if (null == sql || sql.isEmpty()) {
            throw new IllegalArgumentException("非法sql语句异常");
        }
    }

    /**
     * 校验传入的参数和Sql语句所需的参数是否符合,不符合抛出非法参数异常
     * 符合将输入的参数列表提交到对那个的sql位置
     *
     * @param statement  PreparedStatement类型的sql语句执行接口
     * @param parameters 用户提供的参数列表
     * @throws SQLException
     */
    private void handlereStatement(PreparedStatement statement, Object[] parameters) throws SQLException {
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        if (parameterMetaData.getParameterCount() != parameters.length) {
            throw new IllegalArgumentException("Sql语句所需参数不符");
        }
        for (int i = 0; i < parameters.length; i++) {
            statement.setObject(i + 1, parameters[i]);
        }
    }

    /**
     * 通用查询方法
     * 方法所需参数是执行目标的 SQL 语句,对应当前结果集处理方式 ResultSetHandler 接口实现类,
     * 同时利用 ResultSetHandler 类型约束泛型对应具体数据类型,也是同时约束当前方法对应的返回
     * 值类型。方法还需要给予 SQL 语句所需参数列表,返回值类型由 ResultSetHandler 处理器接口
     * 约束。
     *
     * @param sql        目标查询执行的 SQL 语句
     * @param rsh        ResultSetHandler 结果集处理器接口实现类对象,同时约束泛型,也就是约束方法
     *                   返回值类型
     * @param parameters 对应的 SQL 语句的参数列表,为 Object 类型不定长参数
     * @param <T>        自定义泛型占位符,主要约束当前方法的返回值结果
     * @return 根据当前使用的 ResultSetHandler 结果集处理器方式,返回值对应 ResultSet 最终数据
     * 处理结果
     */
    public <T> T query(String sql, ResultSetHandler<T> rsh, Object... parameters) throws SQLException {
        check(sql);
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Connection connection = null;
    
        connection = JdbcUtils.getConnection();
        T t = null;
        try {
            statement = connection.prepareStatement(sql);
            handlereStatement(statement, parameters);
            resultSet = statement.executeQuery();
            t = rsh.handler(resultSet);
        } catch (SQLException e) {
            throw e;
        } finally {
            JdbcUtils.close(connection, statement, resultSet);
        }
        return t;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值