抽象类配合泛型实现通用dao层,通过abstractdao封装save、findbyid、deletebyid等主键驱动操作,子类继承时传入class以兼顾编译期类型安全与运行时类型获取,不包含业务查询、事务、缓存等横切逻辑。

抽象类配合泛型实现通用 DAO 层,核心是用抽象类承载可复用的 CRUD 逻辑,再通过泛型参数绑定实体类型与主键类型,既避免接口无法提供实现的限制,又绕开泛型擦除带来的运行时类型丢失问题。
用抽象类声明泛型参数并封装通用操作
定义 AbstractDao
- save(T entity):调用 ORM 框架的保存逻辑,无需强制子类重复实现
- findById(ID id):统一处理空值、异常和日志,返回 Optional
或 null - deleteById(ID id):校验主键非空后执行删除,子类不用再写防御代码
- 构造时接收 Class
:如 protected AbstractDao(Class entityClass),用于反射获取表名、字段元数据或创建新实例
子类显式传递类型参数并注入具体能力
每个业务 DAO 继承抽象类时,必须明确指定泛型实参,并在构造中传入对应 Class 对象:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- public class UserDAO extends AbstractDao
{ public UserDAO() { super(User.class); } } - 这样既能保证编译期类型安全(比如 findById 返回 User 而非 Object),又让运行时能拿到 User.class 做动态 SQL 构建或 Hibernate 实体注册
- 若使用 Spring,可通过 @Autowired 注入 JdbcTemplate 或 SessionFactory,再由抽象类统一管理模板调用逻辑
把条件查询和分页留给子类或 Service 层
抽象类只保留无业务语义的“主键驱动”操作。带 where、order、limit 的方法不属于通用范畴:
- 不定义 findByEmail(String)、findPage(Pageable) 这类泛型方法——它们会污染契约、增加实现负担
- 子类可按需扩展:UserDAO 可额外声明 List
findByStatus(String status) - 分页建议由 Service 封装:先调用 findAll() 或自定义查询,再用 PageUtil.toList(page, size) 切片,保持 DAO 纯净
事务、缓存、日志等横切关注点不进抽象类
DAO 抽象类只做数据搬运,不承担职责外的逻辑:
- 不加 @Transactional:事务边界应在 Service 方法上声明
- 不引入 RedisTemplate 或 @Cacheable:缓存策略由上层统一控制更灵活
- 日志记录可留钩子(如 protected void onBeforeSave(T entity)),但默认空实现,子类按需重写
- 避免耦合具体 ORM:抽象类用 protected 方法暴露 template 执行入口,而非直接依赖 JpaOperations 或 SqlSession
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










