BaseDao核心能力包括:统一执行增删改、通用查询单个/多个对象、资源自动安全关闭、全程使用PreparedStatement防注入;依赖JDBCUtils解耦连接与关闭,通过反射自动映射ResultSet到实体。

Java 中封装通用 DAO 层,核心是把 JDBC 固定流程抽离成可复用的 BaseDao,让 StudentDao、UserDao 这类具体 DAO 只需关注 SQL 和实体,不用重复写连接、预编译、资源关闭等代码。
BaseDao 要覆盖哪些关键能力
一个实用的 BaseDao 至少要支持以下四点:
- 统一执行增删改(update):接收 SQL 字符串和参数数组,自动用 PreparedStatement 设置 ? 占位符并执行 executeUpdate()
- 通用查询单个对象(queryOne):传入 SQL、参数、目标实体类 Class,自动映射 ResultSet 的一行到对应对象
- 通用查询多个对象(queryList):同上,但返回 List<T>,空结果返回空集合而非 null
- 资源自动管理:Connection、PreparedStatement、ResultSet 在 finally 块中按序安全关闭,避免泄漏
SQL 参数必须用 PreparedStatement
所有对外暴露的方法,SQL 中的动态值一律用 ? 占位,参数通过 Object[] 或可变参数传入。例如:
- 插入:
"INSERT INTO user(name, age) VALUES (?, ?)",参数为new Object[]{"张三", 25} - 条件查询:
"SELECT * FROM user WHERE id = ? AND status = ?",参数为new Object[]{101, "ACTIVE"}
硬拼 SQL 字符串(如 "WHERE id = " + id)会引发 SQL 注入,BaseDao 必须杜绝这种写法。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
结果集自动映射靠反射 + 属性名匹配
查出 ResultSet 后,BaseDao 利用 Java 反射遍历实体类所有 setter 方法,将 ResultSet 中列名(如 username)与属性名(username)匹配,调用对应 setXxx() 赋值。常见做法有:
- 用
ResultSetMetaData获取列名,转为小驼峰格式后匹配字段 - 借助 Apache Commons BeanUtils 的
BeanUtils.populate(obj, map)简化映射逻辑 - 要求数据库字段名与 Java 实体属性名严格一致(最简单,适合初期项目)
连接和关闭交给工具类解耦
BaseDao 不直接操作 DriverManager 或连接池,而是依赖一个 JDBCUtils 工具类:
-
JDBCUtils.getConnection():内部可基于 Druid、Hikari 或纯 DriverManager,切换只需改这一个方法 -
JDBCUtils.close(rs, pstmt, conn):重载支持任意组合关闭,且对 null 安全
这样 BaseDao 本身完全不绑定具体连接方式,后续升级连接池或加事务代理,DAO 层零改动。

















