05.jdbc PreparedStatement 执行查询

it2022-05-05  158

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开始返回Objectpublic 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); }

最新回复(0)