java泛型dao通过解耦操作行为与数据类型实现类型安全的通用crud:定义泛型接口约束t extends baseentity,业务接口继承并扩展,框架复用class绕过类型擦除,结合多数据源策略提升灵活性。

Java 通过泛型实现通用 DAO 模式,核心是把“操作行为”和“数据类型”解耦——接口只定义 能做什么,具体类决定 对哪种实体做、怎么做。不写重复代码,也不牺牲类型安全。
定义泛型 DAO 接口,统一 CRUD 契约
声明一个带类型参数 T 的接口,覆盖基础数据操作,不绑定任何具体实体或数据库细节:
-
<t> void save(T entity)</t>—— 接收任意实体,编译期检查传入是否为 T 类型 -
<t id> T findById(ID id)</t>—— 主键类型也可泛化(如 Long、String、UUID) -
<t> List<t> findAll()</t></t>—— 返回明确类型的集合,调用方无需强制转型 - 可约束
T extends BaseEntity,确保所有实体提供getId()、getVersion()等通用能力
业务 DAO 接口继承泛型接口,按需扩展
避免把所有查询塞进一个大接口,采用分层继承方式保持清晰和可维护:
-
IUserDao extends GenericDao<user long></user>—— 固定实体与主键类型 - 在
IUserDao中额外声明业务方法:List<user> findByEmail(String email)</user> -
IOrderDao extends GenericDao<order long></order>同理,各自独立又共享通用方法 - 上层 Service 可以依赖
GenericDao>做通用处理(如日志、权限校验),也可直接注入具体接口
实现类复用框架能力,绕过泛型擦除限制
Java 泛型在运行时被擦除,所以不能直接用 T.class。常用且可靠的做法是:
- 构造时显式传入
Class<t></t>:例如new JdbcGenericDao(User.class),后续可用它获取表名、字段等元数据 - 优先基于成熟框架封装:MyBatis-Plus 的
BaseMapper<t></t>、Spring Data JPA 的JpaRepository<t id></t>已内置类型推导,自研实现建议直接复用 - 避免在通用实现中硬编码事务或缓存逻辑——这些应由 Service 层控制,DAO 只专注数据操作
配合多态与策略,支撑多数据源或动态行为
泛型 DAO 不是孤立的,要和运行时能力联动才能真正灵活:
- 让不同数据源有各自的泛型基类:如
AbstractJdbcDao<t></t>、AbstractMongoDao<t></t>,内部封装对应连接路由逻辑 - 用
IDataSourceAware<t></t>这类标记接口声明“支持切换数据源”,再通过withDataSource("tenant_001")动态绑定 - 结合策略模式:根据实体类型
T.class或注解(如@TenantIsolated)自动选择数据源,启动时缓存映射关系,避免每次反射
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











