抽象类在DAO层定义泛型BaseDao<T,ID>统一CRUD契约,封装连接管理、SQL执行与异常处理,强制子类实现SQL和映射逻辑,预留钩子方法支持扩展,实现复用性与灵活性平衡。

抽象类在数据访问层(DAO 层)定义标准 CRUD 框架,核心是把通用操作逻辑上提、把差异部分留给子类实现。它不直接操作数据库,而是提供统一方法签名和基础流程控制,让具体 DAO 类只关注 SQL 细节或实体映射。
定义泛型抽象 DAO 类
用泛型约束实体类型和主键类型,避免重复写 UserDao、OrderDao 等多个非泛型接口:
- 声明为
abstract class BaseDao<T, ID>,其中T是实体类(如User),ID是主键类型(如Long或String) - 定义抽象方法:例如
protected abstract String getInsertSql()、protected abstract T mapRow(ResultSet rs),强制子类提供 SQL 和结果映射逻辑 - 提供默认实现的模板方法:如
public T insert(T entity)调用getInsertSql()+executeUpdate()+ 主键回填逻辑
封装共用数据库操作能力
抽象类内聚合连接获取、参数设置、资源释放等重复代码,不暴露 JDBC 细节给子类:
- 持有
DataSource或注入ConnectionProvider,子类无需关心如何获取连接 - 内置
executeQuery(String sql, Object... args)方法:自动创建PreparedStatement、设参、遍历ResultSet并调用子类的mapRow() - 统一异常处理:将
SQLException转为运行时异常(如自定义DataAccessException),避免子类到处try-catch
留出可扩展钩子点
通过模板方法模式预留定制入口,适应不同实体的特殊需求:
立即学习“Java免费学习笔记(深入)”;
- 定义
protected void beforeInsert(T entity)和protected void afterInsert(T entity),子类可补充生成 ID、记录日志等逻辑 - 对批量操作支持:提供
public int[] batchInsert(List<T> entities),内部调用子类的getBatchInsertSql()和setBatchParams(PreparedStatement, T) - 允许覆盖默认事务行为:如
public boolean isTransactional()默认返回true,子类可按需关闭
子类只需实现最小契约
具体 DAO 继承后,仅需提供 SQL 和映射,其余全部复用:
UserDao extends BaseDao<User, Long>- 重写
getSelectByIdSql()→"SELECT id, name, email FROM user WHERE id = ?" - 重写
mapRow(ResultSet rs)→ 构造new User(rs.getLong("id"), rs.getString("name")) - 重写
getInsertSql()→"INSERT INTO user(name, email) VALUES(?, ?)",并实现setInsertParams(PreparedStatement ps, User u)
这样既保证了所有 DAO 具备一致的 CRUD 行为语义,又保持了对不同表结构、主键策略、SQL 方言的灵活适配能力。不是靠继承“功能”,而是继承“契约”与“骨架”。


















