Spring JDBC通用CRUD框架设计与实现

发布时间:2026/9/17 19:14:02
Spring JDBC通用CRUD框架设计与实现
1. 项目概述今天给大家分享一个基于Spring JDBC Template封装的通用CRUD框架实现。这个框架是我在实际项目中经过多次迭代优化后的成果能够显著减少重复的数据库操作代码提升开发效率。这个框架的核心设计理念是通过泛型和反射机制实现对任意实体类的CRUD操作。相比传统的MyBatis或Hibernate方案它更加轻量级不需要复杂的XML配置或注解同时保留了Spring JDBC的性能优势。2. 框架设计思路2.1 基础架构设计框架的核心架构分为三层模型层定义所有实体类的基类BaseModel包含通用字段接口层定义通用的CRUD操作接口BaseDao实现层提供BaseDao的默认实现BaseDefaultDao这种分层设计使得框架既保持了灵活性可以自定义实现又提供了开箱即用的功能。2.2 关键技术选型框架主要依赖以下技术Spring JDBC Template作为底层数据库操作引擎Lombok简化Java Bean的编写FastJson用于JSON序列化反射机制实现对象与数据库表的自动映射选择这些技术主要基于以下考虑Spring JDBC Template比纯JDBC更方便比ORM框架更轻量反射机制虽然有一定性能损耗但在大多数业务场景中可以接受这些依赖都是Spring生态中的常见组件学习成本低3. 核心实现解析3.1 BaseModel设计BaseModel是所有实体类的基类主要作用有Data public abstract class BaseModel implements Serializable { static final long serialVersionUID 25456241672452L; private Long id; private String createBy; private String updateBy; private LocalDateTime createDate; private LocalDateTime updateDate; public abstract String tableName(); }关键设计点使用抽象类而非接口可以定义公共字段包含审计字段创建人、修改人等符合企业开发规范要求子类必须实现tableName()方法明确指定对应的数据库表名3.2 BaseDao接口设计BaseDao定义了标准的CRUD操作接口public interface BaseDaoM extends BaseModel { M findByPk(Long pk); void create(M model); void update(M model); void delete(M model); PageResponseM query(PageRequest request); }这个接口使用了泛型可以支持任何继承自BaseModel的实体类。3.3 BaseDefaultDao实现这是框架的核心实现类主要功能包括3.3.1 查询单条记录Override public M findByPk(Long pk) { try { if (pk null) { throw new ExamRuntimeException(pk cant not be null); } M model (M) ReflectionUtil.getSuperGenericityInstance(this.getClass(), 1); StringBuilder sql new StringBuilder(select * from ) .append(model.tableName()) .append( where 11 and id ?;); MapString, Object resultMap jdbcTemplate.queryForMap(sql.toString(), pk); resultMap.forEach((field, val) - { Method setMethod ReflectionUtil.getSetMethodByField( ReflectionUtil.getFieldByName(StringUtil.toCame(field), model.getClass()), model.getClass()); ReflectionUtil.invokeMethod(setMethod, model, val); }); return model; } catch (EmptyResultDataAccessException emptyResultDataAccessException) { throw new ExamRuntimeException(查无数据); } }实现要点使用反射创建模型实例自动构建SQL查询语句将查询结果映射到模型对象3.3.2 新增记录Override public void create(M model) { if (model.getId() null){ model.setId(IdUtil.DEFAULT_SNOWFLAKE.nextId()); } // 设置审计字段 if (model.getCreateDate() null){ model.setCreateDate(LocalDateTime.now()); } if (model.getUpdateDate() null){ model.setUpdateDate(LocalDateTime.now()); } model.setCreateBy(SpringUtil.getBean(LoginProvide.class).takeCreateBy()); model.setUpdateBy(model.getCreateBy()); // 获取所有字段 ListString fields ReflectionUtil.allFields(model.getClass(), serialVersionUID); ListObject fieldVals new ArrayList(); for (String field : fields) { fieldVals.add(ReflectionUtil.getValueByFieldName(field, model.getClass(), model)); } // 构建SQL StringBuilder valSql new StringBuilder(); StringBuilder sql new StringBuilder(insert into ).append(model.tableName()).append((); for (String field : fields) { sql.append(StringUtil.toUnderline(field)).append(,); valSql.append(?).append(,); } sql.delete(sql.length() - 1, sql.length()); valSql.delete(valSql.length() - 1, sql.length()); sql.append()values().append(valSql).append();); jdbcTemplate.update(sql.toString(), fieldVals.toArray()); }实现要点自动生成主键使用雪花算法自动设置审计字段反射获取所有字段值动态构建INSERT语句4. 分页查询实现框架提供了强大的分页查询功能通过PageRequest和PageResponse两个类实现。4.1 PageRequest设计PageRequest封装了分页查询的所有参数public class PageRequest { private Integer currentPage 1; private Integer pageSize 10; private Boolean count true; private String sortField updateDate; private String sortType desc; private Class cls; private Boolean sort true; private Boolean paging true; private Boolean includeLogicDelete false; private MapString, ConditionRuleEnum conditionsRuleMap new HashMap(); private MapString, Object conditionsValMap new HashMap(); // 各种条件设置方法 public PageRequest eq(String field, Comparable val) { this.conditionsRuleMap.put(field, ConditionRuleEnum.EQ); this.conditionsValMap.put(field, val); return this; } // 其他条件方法... }4.2 分页查询实现BaseDefaultDao中的query方法实现了分页查询Override public PageResponseM query(PageRequest request) { BaseModel model null; try { model (BaseModel) request.getCls().newInstance(); } catch (Exception e) { throw new ExamRuntimeException(e); } // 构建基础SQL StringBuilder sql new StringBuilder(select * from ) .append(model.tableName()) .append( where 11 ); ListObject params new ArrayList(); // 添加查询条件 for (Map.EntryString, ConditionRuleEnum entry : request.getConditionsRuleMap().entrySet()) { ConditionRuleEnum conditionRuleEnum entry.getValue(); switch (conditionRuleEnum) { case IN: // 处理IN条件 break; case LIKE: // 处理LIKE条件 break; // 其他条件类型处理... } } // 处理分页和排序 if (request.getSort()) { sql.append( order by ) .append(StringUtil.toUnderline(request.getSortField())) .append( ) .append(request.getSortType()); } if (request.getPaging()) { sql.append( limit ) .append((request.getCurrentPage() - 1) * request.getPageSize()) .append(,) .append(request.getPageSize()); } // 执行查询并返回结果 // ... }5. 使用示例框架的使用非常简单下面是一个完整的使用示例5.1 定义实体类Data public class ExamPaperModel extends BaseModel { private String domain; private String duration; private BigDecimal score; private String title; private String status; private String deleteFlag; private Integer itemCount; private String grade; Override public String tableName() { return exam_paper; } }5.2 定义DAO接口public interface ExamPaperDao extends BaseDaoExamPaperModel { }5.3 使用示例SpringBootTest public class CrudTest { Autowired ExamPaperDao examPaperDao; Test public void testQuery() { PageRequest pageRequest new PageRequest() .like(title, a) .le(deleteFlag, 0) .setPaging(true) .setSort(true) .setCount(true) .setCls(ExamPaperModel.class) .setPageSize(10) .setCurrentPage(1); PageResponseExamPaperModel response examPaperDao.query(pageRequest); System.out.println(JSON.toJSONString(response)); } Test public void testInsert() { ExamPaperModel examPaperModel new ExamPaperModel(); examPaperModel.setDomain(111); examPaperModel.setDuration(222); examPaperModel.setScore(new BigDecimal(1)); examPaperModel.setTitle(ab); examPaperModel.setStatus(ok); examPaperModel.setDeleteFlag(0); examPaperModel.setItemCount(12); examPaperModel.setGrade(一年级); examPaperDao.create(examPaperModel); } }6. 性能优化建议在实际使用中可以考虑以下优化措施缓存反射信息将反射获取的Field和Method缓存起来避免每次操作都进行反射批量操作支持添加批量插入、批量更新等方法SQL预编译对常用SQL进行预编译连接池配置合理配置数据库连接池参数7. 常见问题解决7.1 字段映射问题如果数据库字段名与Java属性名不一致可以在BaseModel子类中添加注解或实现字段名转换方法。7.2 复杂查询支持对于复杂的多表关联查询建议在特定DAO接口中添加自定义方法使用Query注解指定SQL或者使用JdbcTemplate直接编写SQL7.3 事务管理框架本身不处理事务需要在Service层使用Transactional注解管理事务。8. 框架扩展这个基础框架可以根据实际需求进行扩展多数据源支持通过AbstractRoutingDataSource实现读写分离通过AOP拦截将读操作路由到从库分库分表添加分片策略接口审计日志通过切面记录数据变更我在实际项目中使用这个框架后CRUD相关的代码量减少了约70%而且由于统一了数据访问层代码的可维护性也得到了显著提升。特别是对于快速迭代的业务场景这种轻量级的方案比传统的ORM框架更加灵活高效。