java通用dao层通过泛型t解耦类型与行为,用class补全擦除信息,约定实体需无参构造、主键为id或实现identifiable,基类封装反射操作,并推荐基于mybatis-plus或spring data jpa落地。

Java 中在通用 DAO 层规范泛型实体类的增删改查,关键是把“类型”和“行为”解耦:用泛型参数 T 表达实体类型,用接口契约约束操作语义,再通过运行时传入 Class
定义精简、稳定的泛型 DAO 接口
接口只声明所有实体共有的基础操作,避免掺杂业务逻辑或扩展性陷阱:
- save(T entity):统一插入或更新(依据主键是否为空判断)
-
T findById(ID id):ID 类型可设为
Serializable或泛型第二参数<t id></t>,增强主键灵活性 -
List
findAll() :慎用,生产环境建议标记为 @Deprecated 或由子类重写为分页版本 - long count():比全量查询更轻量,适合统计场景
- boolean existsById(ID id):底层用 SELECT 1 FROM ... WHERE id = ?,性能优于 findById
- void deleteById(ID id) 和 void delete(T entity):后者要求实体主键字段已赋值
实体类需满足最小契约约束
为了让泛型逻辑能安全运行,实体类不是任意写的,要遵守几条轻量但关键的约定:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 提供无参构造器(反射实例化必需)
- 主键字段命名统一为
id,或实现Identifiable接口并声明getId()方法 - 推荐继承一个空标记接口(如
interface Entity {}),基类写成BaseDao<t extends entity></t>,编译期即可校验类型合法性 - 若用注解映射(如
@Table、@Id),确保字段与数据库列名有明确对应规则(驼峰转下划线 / 注解显式指定)
基类实现中补全运行时类型信息
泛型擦除后,T 在运行时是 Object。必须显式传递真实类型才能做反射、SQL 构建、结果映射:
- 在抽象基类构造器中接收
Class<t> entityClass</t>并保存为成员变量 - 用
entityClass.getSimpleName().toLowerCase()推导默认表名(如User→user) - 用
entityClass.getDeclaredField("id")获取主键字段类型,决定 SQL 参数占位符绑定方式(Long/String/UUID) - 查询返回时,用
entityClass.getDeclaredConstructor().newInstance()创建实例,再逐字段反射设值
结合主流框架落地,不重复造轮子
手写 JDBC + 反射易出错且难维护。推荐基于成熟框架封装通用层:
-
MyBatis-Plus:直接让 Mapper 接口继承
BaseMapper<t></t>,开箱即用;如需统一软删除、租户隔离等逻辑,自定义MyBaseMapper<t> extends BaseMapper<t></t></t>,再由各业务 Mapper 继承 -
Spring Data JPA:定义
JpaDao<t id> extends JpaRepository<t id></t></t>,利用方法名派生(如findByStatusAndCreateTimeAfter)或@Query补充定制查询 - 若需动态条件构建(如通用列表搜索),可在基类中提供
protected Map<string object> buildQueryParams(T example)</string>,配合反射扫描非空字段生成 WHERE 条件
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










