如何通过JDBC将ResultSet转换为实体对象?
嘿,我完全懂你这种痛点——几百列的表手动映射简直是噩梦,谁想一个个写resultSet.getString("column_name")然后set到实体里啊!而且既然已经拿到了现成的Connection,不想扯DataSource或者重的ORM框架,下面给你几个现成的解决方案,都是别人已经造好的轮子:
方案1:用Apache Commons DbUtils(最省心的轻量工具)
这绝对是你要找的东西!Commons DbUtils是Apache的一个超轻量工具库,核心就是帮你把ResultSet自动映射到实体类,完全不需要DataSource,直接用你手里的Connection,还支持列名到实体字段的自动匹配(默认会把下划线命名的列转成驼峰命名的字段,比如数据库列customer_name对应实体的customerName字段,也可以自定义映射规则)。
步骤:
- 先加依赖(Maven为例):
<dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.8.1</version> <!-- 用最新稳定版即可 --> </dependency>
- 然后直接用
BeanListHandler来把ResultSet转成List<Customer>:
import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.DbUtils; // 你的现有代码:获取Connection、执行查询 Connection con = getMyConnection(); PreparedStatement ps = con.prepareStatement("select * from customers where foo=?"); ps.setString(1, "bar"); ResultSet results = ps.executeQuery(); // 核心转换代码: BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class); List<Customer> customers = handler.handle(results); // 别忘了关资源(DbUtils也有工具类帮你一键关闭) DbUtils.close(ps); DbUtils.close(con);
它会自动根据实体类的字段名(和ResultSet的列名匹配,默认支持驼峰转下划线的映射)来赋值,完全不用你写一行setter代码!如果有个别列名和字段名不匹配,还可以用BasicRowProcessor自定义映射规则,或者给实体加注解(不过默认规则大部分场景都够用)。
方案2:用Spring的BeanPropertyRowMapper(如果你已经用了Spring)
你提到了JdbcTemplate,其实Spring的BeanPropertyRowMapper可以单独拿出来用,不需要绑定JdbcTemplate或者DataSource。它的逻辑和DbUtils类似,也是自动映射列名到实体字段:
import org.springframework.jdbc.core.BeanPropertyRowMapper; // 还是你的现有代码拿到ResultSet Connection con = getMyConnection(); PreparedStatement ps = con.prepareStatement("select * from customers where foo=?"); ps.setString(1, "bar"); ResultSet results = ps.executeQuery(); BeanPropertyRowMapper<Customer> rowMapper = BeanPropertyRowMapper.newInstance(Customer.class); List<Customer> customers = new ArrayList<>(); while (results.next()) { Customer customer = rowMapper.mapRow(results, results.getRow()); customers.add(customer); } // 手动关资源(或者用try-with-resources语法更安全) ps.close(); con.close();
这个的好处是如果你项目里已经有Spring JDBC的依赖,不用再加新的库。它默认也是支持列名驼峰转下划线的映射(比如customer_id对应customerId),如果有特殊需求,也可以重写getColumnMap方法自定义映射。
顺便澄清个小误解
你说JdbcTemplate好像被废弃了——其实真没有!只是个别老旧的方法(比如queryForObject的某些重载)被标记为Deprecated,核心的查询方法都还在维护,而且是Spring JDBC的核心工具。不过它确实需要绑定DataSource,所以不符合你现在用现成Connection的场景,所以前面的方案更适合你。
最后,绝对不推荐自己写反射映射的代码——不是说写不出来,而是边界情况太多了(比如类型转换、null值处理、列名和字段名映射、嵌套实体等等),现成的工具库都已经把这些坑踩过了,直接用就行!
备注:内容来源于stack exchange,提问作者John Little

