JDBC连接数据库第三步:Java利用反射机制将ResultSet结果集遍历到List中

1.基础篇

1.1 反射

反射基础:【Java基础之—反射(非常重要)】

1.2 结果集

结果集Statement:Statement,Statement和ResultSet,Java 中的resultset详解

查询出来的结果集Statement的数据结构,可以看成数据库中一张表的结构,有 N 行 M 列,其中一行就是一条数据。

resultSet.next():将光标从当前位置向前移动一行,即遍历是否还有下一行。

1.3 元数据对象

ResultSetMetaData得到方式: resultSetMetaData = resultSet.getMetaData();

ResultSetMetaData: 检索此 ResultSet对象的列的数量,类型和属性(即每一列的列名和类型)。即描述了ResultSet 结果集中有多少列,列名等等。

int num = resultSetMetaData.getColumnCount(); 获取一行数据的列的数量。

String columName = resultSetMetaData.getColumName (int colum);根据字段的索引值取得字段的名称。

String columType = resultSetMetaData.getColumType (int colum); 根据字段的索引值取得字段的类型,返回值的定义在java.sql.Type类。

除此之外,ResultSetMetaData的方法有:ResultSetMetaData类的介绍

 

2.利用statement执行executeQuery()方法

#commons-beanutils-1.9.3.jar
import org.apache.commons.beanutils.BeanUtils;

public static  List statementExecuteQuery(Class clazz, final String sql){
        T entity = null;
        Statement statement = null;
        ResultSet resultSet = null;
        List queryResult = new ArrayList<>();
        Connection connection= getConnection();
        if (null == connection){
            //log.error("Connection is null.");
            return null;
        }
        try {
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);
            final List> data = converResultSetToList(resultSet);
            for (Map map : data){
                entity = clazz.newInstance();
                for (Map.Entry entry : map.entrySet()){
                    String columnName = entry.getKey();
                    Object columnValue = entry.getValue();
                    BeanUtils.setProperty(entity,columnName,columnValue);
                }
                queryResult.add(entity);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeResource(connection,null,null,resultSet);
        }
        return queryResult;
    }

    public static  T statementQuery(Class clazz, final String sql){
        List queryResult = statementExecuteQuery(clazz,sql);
        if (null != queryResult && queryResult.size() > 0){
            return queryResult.get(0);
        }
        return null;
    }

3.将resultset转换为list

private static List> converResultSetToList(ResultSet resultSet) throws SQLException {
        if (null == resultSet){
            return null;
        }
        List> data = new ArrayList<>();
        ResultSetMetaData rsmd = resultSet.getMetaData();
        while (resultSet.next()){
            Map rowData = new HashMap();
            for(int i = 0,columnCount = rsmd.getColumnCount();i < columnCount; i++){
                rowData.put(rsmd.getColumnName(i + 1),resultSet.getObject(i + 1));
            }
            data.add(rowData);
        }
        return data;
    }

其实,在这里有一个很有学问的知识点,就是JDBC元数据对象。

前面查询方法 statementExecuteQuery() 可以支持的 sql 语句不支持填充占位符,但可以是一下三种 sql 语句:

(1)SELECT * FROM userinfos WHERE userName = 'aerfa'

(2)SELECT userName , password , data , address FROM userinfos WHERE userName = 'aerfa';

看得出来,支持以上两种sql语句,就必须要求数据库中表的字段名称(即列名)要与User类的属性名称一样才行。

从结果集中可以get到元数据对象ResultSetMetaData,结果集中的每一条的数据的列名就可以由元数据对象得到。且,得到的列名与User类的属性名称一致,把列名和对应的value值放在map中,然后遍历就可以通过反射机制将每一条数据转换为JavaBean了。

那么,问题来了,我们在数据库中设置字段名的时候,一般含有两个单词的列名中间以下划线相隔,例如userName ---> user_name。这个时候,数据表的字段的列名和对应的实体类的属性名就不一致了,怎么写sql语句呢?

此时,可以按照(3)的格式写sql语句:

(3)SELECT user_name userName , password , data , address  FROM userinfos WHERE user_name = 'aerfa';

解释:其实我们想要的结果就是结果集中的列名要与对应的实体类的属性名称一直,此时我们只需要给user_name字段取一个别名userName,这个别名就是对应的实体类的属性名。当然,比如 数据表字段 password 本身就与对应的实体类的属性名称一直,就不再取别名了,因为别名就是它本身。这样我们查出来的结果集的列名就是以别名命名的,即列名一次就是:userName , password , data , address,这就与User的属性名一致了。

4.利用preparedStatement执行executeQuery()方法

public static  List preparedStatementExecuteQuery(Class clazz,final String sql, Object... args){
        T entity = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List queryResult = new ArrayList<>();
        Connection connection = getConnection();
        if(null == connection){
            return null;
        }
        try {
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0, length = args.length; i < length; i++){
                preparedStatement.setObject(i + 1, args[i]);
            }
            resultSet = preparedStatement.executeQuery();
            final List> data = converResultSetToList(resultSet);
            for (Map map: data){
                entity = clazz.newInstance();
                for(Map.Entry entry: map.entrySet()){
                    String columnName = entry.getKey();
                    Object columnValue = entry.getValue();
                    BeanUtils.setProperty(entity,columnName,columnValue);
                }
                queryResult.add(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeResource(connection,null,preparedStatement,resultSet);
        }
        return queryResult;
    }

    public static  T preparedStatementQuery(Class clazz, final String sql, Object... args){
        List queryResult = preparedStatementExecuteQuery(clazz,sql,args);
        if (null != queryResult && queryResult.size() > 0){
            return queryResult.get(0);
        }
        return null;
    }

4.测试结果

JDBC连接数据库第三步:Java利用反射机制将ResultSet结果集遍历到List中_第1张图片

你可能感兴趣的:(Java,EE)