05.jdbc PreparedStatement 执行查询

jdbc 系列文章列表, 请查看目录: 《jdbc学习笔记》

PreparedStatement 执行查询和执行增删改操作流程没有太大区别, 只有两点:

  • 查询使用的方法是 PreparedStatemnet.executeQuery();
  • 查询结果返回的是ResultSet, 需要进行解析.

1. ResultSet简介

  • ResultSet 数据结构类似于一个二维数组和游标的结合, 和普通的java 数据结构有点儿不太一样.
  • 默认情况下, 游标指向二维表头, 需要通过next()方法移动游标. 因此纵使只有一行数据, 在解析之前也得调用next()方法移动游标.
  • ResultSet ApI 比较多, 笔者列出一些笔者认为比较常用的API:
方法签名 方法描述 返回值
boolean next() 判断结果集中是否还有数据, 同时向下移动游标 返回true, 表示结果集中还有数据; 返回false, 表示无数据
ResultSetMetaData getMetaData() 获取结果集的元数据信息, 返回结果可读取含列的 列名, 列别名, 列类型等信息
Object getObject(int columnIndex) 获取列值, 索引为数字下标, 从1开始 返回Object
public T getObject(int columnIndex, Class type) 获取列值, 索引下标从1开始 返回期望类型T, 自动类型转换.
可能会抛出类型转换异常
Object getObject(String columnLabel) 获取列值, 索引为类名或列别名. 返回Object类型
public T getObject(String columnLabel, Class type) 获取列值, 索引为类名或列别名. 返回结果约束和get(int, Class)类似
Object get[Int|Long|String|Float|Double…](int columnIndex) 获取列值, 索引下标从1开始 返回Object类型
Object get[Int|Long|String|Float|Double…](String columnLabel) 获取列值, 列名可为列名或列别名 返回Object类型

2. 测试

为了使代码更清晰, 笔者的测试用例不再使用try-catch包裹, 直接采取throws的方式.

2.1 查询单个字段

  • 由于ResultSet 游标默认在表头, 所以纵使只有一条数据, 那么也需要调用next()方法使游标向下移动一行.
  • 由于笔者清楚, 通过主键id查询只有一条记录, 所以通过if 移动一次游标, 解析一次结果即可
  • 由于很清楚name 可转换为String 类型, 所以直接调用resultSet 的getString方法获取值即可.
 @Test
public void test_queryNameById() throws Exception {

    // 1. 获取数据库连接, 自动提交事务
    Connection connection = DbConnUtil.getConnection();

    String sql = "select id, name, password pwd from t_user where id = ?";

    // 2. 获取PreparedStatement
    PreparedStatement preparedStatement = connection.prepareStatement(sql);

    // 3. 设置查询参数
    preparedStatement.setInt(1, 1005);

    // 4. 执行查询sql
    ResultSet resultSet = preparedStatement.executeQuery();

    // 5.结果集解析
    if (resultSet.next()) {
        String name = resultSet.getString("name");
        System.out.println(name);
    }

    // 6.释放资源
    DbConnUtil.release(resultSet, preparedStatement, connection);
}

2.2 查询结果转换为单个java Bean

  • 查询结果依然为一行数据, 只是有三列.
  • 笔者尝试用多种方式综合获取各列的值, 基本涵盖了ResultSet所支持的API:
    • API 采用getInt(), getString(), getObject()
    • 索引采用序号索引, 列名索引, 列别名索引
@Test
public void test_queryUserById() throws Exception {

    // 1. 获取数据库连接, 自动提交事务
    Connection connection = DbConnUtil.getConnection();

    String sql = "select id, name, password pwd from t_user where id = ?";

    // 2. 获取PreparedStatement
    PreparedStatement preparedStatement = connection.prepareStatement(sql);

    // 3. 设置查询参数
    preparedStatement.setInt(1, 1005);

    // 4. 执行查询sql
    ResultSet resultSet = preparedStatement.executeQuery();

    // 5.结果集解析
    UserPO userPO = new UserPO();
    if (resultSet.next()) {
        userPO.setId(resultSet.getInt(1));
        userPO.setName(resultSet.getString("name"));
        userPO.setPassword(resultSet.getObject("pwd", String.class));
    }

    System.out.println(userPO);

    // 6.释放资源
    DbConnUtil.release(resultSet, preparedStatement, connection);
}

2.3 查询结果转换为bean列表

  • 解析结果为bean列表和解析为bean方式基本没太大区别, 只是将if替换成了while
@Test
public void test_queryUserListById() throws Exception {

    // 1. 获取数据库连接, 自动提交事务
    Connection connection = DbConnUtil.getConnection();

    String sql = "select id, name, password pwd from t_user";

    // 2. 获取PreparedStatement
    PreparedStatement preparedStatement = connection.prepareStatement(sql);

    // 3. 执行查询sql
    ResultSet resultSet = preparedStatement.executeQuery();

    // 4.结果集解析
    List<UserPO> userList = new ArrayList<>();
    while (resultSet.next()) {
        UserPO userPO = new UserPO();
        userPO.setId(resultSet.getInt(1));
        userPO.setName(resultSet.getString("name"));
        userPO.setPassword(resultSet.getObject("pwd", String.class));
        userList.add(userPO);
    }
    userList.forEach(System.out::println);

    // 5.释放资源
    DbConnUtil.release(resultSet, preparedStatement, connection);
}

2.4 查询单个bean转换为Map

 @Test
public void test_queryUserMapById() throws Exception {

    // 1. 获取数据库连接, 自动提交事务
    Connection connection = DbConnUtil.getConnection();

    String sql = "select id, name, password pwd from t_user where id = ?";

    // 2. 获取PreparedStatement
    PreparedStatement preparedStatement = connection.prepareStatement(sql);

    // 3. 设置查询参数
    preparedStatement.setInt(1, 1005);

    // 4. 执行查询sql
    ResultSet resultSet = preparedStatement.executeQuery();

    // 5.结果集解析
    Map<String, Object> map = new HashMap<>();

    // 获取结果集元数据信息
    ResultSetMetaData metaData = resultSet.getMetaData();

    if (resultSet.next()) {
        // 解析列别名和列值, 需要注意的是下标从1开始
        for (int i = 1; i <= metaData.getColumnCount(); i++) {
            String columnLabel = metaData.getColumnLabel(i) + "/" + metaData.getColumnName(i);
            map.put(columnLabel, resultSet.getObject(i));
        }
    }

    // 输出map信息
    map.entrySet().forEach(entry -> System.out.println(entry.getKey() + ":" + entry.getValue()));

    // 6.释放资源
    DbConnUtil.release(resultSet, preparedStatement, connection);
}

你可能感兴趣的:(jdbc)