数据库查询结果封装的核心是将resultset每行转为java结构,常用arraylist+hashmap组合:arraylist有序存储多行,hashmap以字段名为key映射值,支持动态字段与通用dao。

数据库查询结果封装的核心,是把 ResultSet 中每一行数据转换成程序可操作、易传递的 Java 结构。用 ArrayList 承载多行,用 HashMap 表示单行——这种组合既灵活又无需提前定义实体类,特别适合动态字段、快速原型或通用 DAO 场景。
为什么选 ArrayList + HashMap
ArrayList 提供有序、可索引、自动扩容的容器能力,适合逐行追加结果;HashMap 以字段名为 key、值为 value,天然匹配数据库列名与内容的映射关系。两者结合后,你可以这样访问数据:
-
第 0 行的 name 字段 →
list.get(0).get("name") -
遍历所有邮箱 →
for (Map<string object> row : list) { System.out.println(row.get("email")); }</string> -
兼容别名和大小写敏感字段 → 使用
rs.getObject(columnLabel)比靠序号更健壮
封装过程的关键步骤
不依赖框架时,手动封装需注意三点:元数据读取、空值处理、资源释放。
- 调用
resultSet.getMetaData()获取列数和列名,避免硬编码列索引 - 用
rs.getObject(i)或rs.getObject(columnName)读值,它能自动适配各种 JDBC 类型(如 DATE、BIGINT、NULL) - 每行新建一个
new HashMap(),填入键值对后list.add(rowMap) - 务必在
finally或 try-with-resources 中关闭 ResultSet、Statement、Connection
常见陷阱与应对
看似简单,但实际容易出错的地方集中在类型和命名上。
-
字段名大小写问题:MySQL 默认不区分,但 PostgreSQL 和 Oracle 区分;建议统一用小写存入 HashMap,或用
rsmd.getColumnLabel(i)获取 SQL 中定义的别名 -
NULL 值导致 NPE:
rs.getObject()返回 null 是合法的,使用前应判断,或用Optional.ofNullable(row.get("age")).orElse(0) -
日期/时间类型乱码:避免用
getString()读 datetime,优先用getObject()得到 LocalDateTime 或 Timestamp,再按需格式化 -
中文字段名支持:只要数据库和连接 URL 设置了
useUnicode=true&characterEncoding=UTF-8,字段名就能正常识别
轻量替代方案:record(Java 14+)
如果字段固定、结构明确,比 Map 更推荐用 record:
- 类型安全:编译期检查字段名和类型
- 零样板代码:自动生成构造器、equals、toString
- 语义清晰:
List<user> users = ...</user>比List<map object>></map>更易维护 - 示例:
record User(String name, int age, String email) {},封装时直接new User(rs.getString("name"), rs.getInt("age"), rs.getString("email"))










