# 基础服务层 **本文引用的文件** - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本章节面向“基础服务层”,聚焦以下目标: - IBaseService 接口提供的通用CRUD、分页查询与批量操作能力 - BaseServiceImpl 的实现细节,包括事务管理、数据验证、异常处理 - CrmBaseMapper 对 MyBatis Plus 的扩展,如自定义SQL注入器、动态条件构建等高级特性 - 如何基于该基础层进行服务扩展与自定义业务逻辑实现 ## 项目结构 基础服务层位于 crm-base 模块,围绕“接口-实现-Mapper-配置”分层组织: - service/IBaseService:定义通用服务接口 - service/impl/BaseServiceImpl:通用服务实现 - mapper/CrmBaseMapper:扩展 MyBatis Plus Mapper - config/*:MyBatis Plus 配置、SQL注入器、元对象填充、全局异常处理等 - domain/*:实体基类、结果封装、枚举、异常等 ```mermaid graph TB subgraph "基础服务层" IBase["IBaseService"] Impl["BaseServiceImpl"] Mapper["CrmBaseMapper"] MPConf["MybatisPlusConfig"] SQLI["CrmSqlInjector"] Fill["MetaObjectFillHandler"] ExAd["GlobalExceptionHandlerAdvice"] Result["Result / PageResult"] BE["BaseEntity / OwnedEntity"] end IBase --> Impl Impl --> Mapper Impl --> Result Impl --> BE Mapper --> MPConf MPConf --> SQLI MPConf --> Fill ExAd --> Result ``` 图表来源 - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) 章节来源 - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) ## 核心组件 - IBaseService:定义通用CRUD、分页查询、批量操作的统一接口契约,供各业务服务继承或组合使用。 - BaseServiceImpl:基于 MyBatis Plus 的 ServiceImpl 提供默认实现,封装事务、参数校验、异常转换、分页与批量方法。 - CrmBaseMapper:扩展 MyBatis Plus 的 BaseMapper,提供统一的查询构造、动态条件、批量操作等能力。 - MybatisPlusConfig + CrmSqlInjector:注册自定义SQL注入器,为Mapper注入通用方法(如动态条件查询、批量插入更新)。 - MetaObjectFillHandler:自动填充审计字段(创建时间、更新时间、创建人等),保证数据一致性。 - GlobalExceptionHandlerAdvice:统一异常捕获与响应封装,将业务异常转换为标准 Result 返回。 章节来源 - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) ## 架构总览 下图展示了从控制器到服务层再到数据访问层的调用链,以及基础服务层在其中的作用。 ```mermaid sequenceDiagram participant C as "控制器" participant S as "业务服务(继承IBaseService)" participant BS as "BaseServiceImpl" participant M as "CrmBaseMapper" participant DB as "数据库" C->>S : "调用CRUD/分页/批量方法" S->>BS : "委托通用实现" BS->>BS : "参数校验/事务边界" BS->>M : "执行SQL(含动态条件/批量)" M-->>BS : "返回结果集/影响行数" BS-->>S : "封装Result/PageResult" S-->>C : "统一响应" ``` 图表来源 - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) ## 详细组件分析 ### IBaseService 接口设计 - 职责:定义通用CRUD、分页查询、批量操作的方法签名,确保各业务服务具备一致的数据访问能力。 - 典型能力: - 单条/批量新增、修改、删除 - 按ID获取、条件查询、分页查询 - 批量更新(支持部分字段) - 返回统一结果类型(Result/PageResult) - 设计要点: - 泛型约束实体类型,便于类型安全 - 输入参数与输出结果采用DTO/Param/VO分离,避免泄露内部模型 - 分页查询返回 PageResult,包含数据列表与分页信息 章节来源 - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) ### BaseServiceImpl 实现细节 - 事务管理: - 关键写操作(新增、修改、删除、批量)包裹在事务中,保证原子性 - 读操作通常非事务或只读事务,减少锁竞争 - 数据验证: - 入参非空校验、业务规则校验(如唯一性检查) - 结合实体注解与自定义校验器,统一错误提示 - 异常处理: - 捕获并转换底层异常为业务异常 - 通过全局异常处理器统一封装为 Result - 分页与批量: - 分页查询使用 MyBatis Plus 的分页插件,配合动态条件构建 - 批量操作优先使用批处理器,降低往返开销 - 审计字段填充: - 借助 MetaObjectFillHandler 自动填充创建/更新时间、操作人等 ```mermaid flowchart TD Start(["进入写方法"]) --> Check["参数校验"] Check --> Valid{"校验通过?"} Valid --> |否| Err["抛出业务异常"] Valid --> |是| TxStart["开启事务"] TxStart --> Exec["执行持久化操作"] Exec --> Success{"是否成功?"} Success --> |否| Rollback["回滚事务"] Success --> |是| Commit["提交事务"] Commit --> End(["返回结果"]) Rollback --> End Err --> End ``` 图表来源 - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) 章节来源 - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) ### CrmBaseMapper 与 MyBatis Plus 扩展 - 扩展点: - 继承 MyBatis Plus 的 BaseMapper,提供通用CRUD能力 - 通过自定义 SQL 注入器注入动态条件查询、批量方法 - 动态条件构建: - 支持多条件组合(等于、模糊、范围、IN等) - 可结合实体属性生成 WHERE 片段,避免手写SQL - 批量操作: - 批量插入/更新,利用数据库特性优化性能 - 支持 ON DUPLICATE KEY UPDATE 或 MERGE 语义(由注入器决定) - 分页查询: - 与分页插件集成,自动拼接 LIMIT/OFFSET 或等效语法 ```mermaid classDiagram class CrmBaseMapper { +selectListByCondition(query) List +insertBatch(list) int +updateBatchById(list) int +deleteByIds(ids) int } class MybatisPlusConfig { +registerSqlInjector() +paginationInterceptor() } class CrmSqlInjector { +addCustomMethod() } CrmBaseMapper --> MybatisPlusConfig : "被配置注册" MybatisPlusConfig --> CrmSqlInjector : "注入自定义方法" ``` 图表来源 - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) 章节来源 - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) ### 实体基类与审计字段 - BaseEntity: - 定义通用字段(如主键、状态、删除标记等) - 与填充处理器协作,自动维护审计字段 - OwnedEntity: - 在 BaseEntity 基础上增加数据权限相关字段(如所属部门、归属人) - 配合数据可见性上下文,实现行级权限控制 ```mermaid classDiagram class BaseEntity { +id +createTime +updateTime +creator +updater } class OwnedEntity { +ownerId +deptId } BaseEntity <|-- OwnedEntity ``` 图表来源 - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) 章节来源 - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) ## 依赖关系分析 - 组件耦合: - BaseServiceImpl 依赖 CrmBaseMapper 完成数据访问 - MybatisPlusConfig 负责装配 CrmSqlInjector 与分页插件 - MetaObjectFillHandler 与实体基类协作完成审计字段填充 - GlobalExceptionHandlerAdvice 统一捕获异常并封装为 Result - 外部依赖: - MyBatis Plus:ORM框架、分页插件、SQL注入机制 - 数据库驱动:具体SQL方言由注入器适配 ```mermaid graph LR Impl["BaseServiceImpl"] --> Mapper["CrmBaseMapper"] Mapper --> MPConf["MybatisPlusConfig"] MPConf --> SQLI["CrmSqlInjector"] Impl --> Fill["MetaObjectFillHandler"] Impl --> Ex["GlobalExceptionHandlerAdvice"] Impl --> Res["Result/PageResult"] ``` 图表来源 - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) 章节来源 - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) ## 性能考量 - 分页查询: - 使用分页插件避免全表扫描,合理设置 page/size - 复杂条件查询建议建立合适索引 - 批量操作: - 优先使用批量插入/更新,减少网络往返 - 大批量数据分片提交,避免单次事务过大 - 事务边界: - 缩小事务范围,避免长事务导致锁竞争 - 读多写少场景尽量使用只读事务 - 填充与校验: - 审计字段填充在写入前完成,避免额外更新 - 校验失败尽早返回,减少无效DB交互 [本节为通用指导,不直接分析具体文件] ## 故障排查指南 - 常见异常: - 参数校验失败:检查入参非空与业务规则 - 事务回滚:查看日志中的异常堆栈,定位失败SQL或约束冲突 - 分页异常:确认分页参数合法性与排序字段存在 - 调试建议: - 开启 MyBatis SQL 日志,观察实际执行的SQL - 使用全局异常处理器返回的 Result 快速定位错误码与消息 - 针对批量操作,逐步缩小批次大小定位问题 章节来源 - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) ## 结论 基础服务层通过 IBaseService 与 BaseServiceImpl 提供了稳定、一致的CRUD与分页、批量能力;CrmBaseMapper 与自定义 SQL 注入器增强了动态条件与批量处理能力;MetaObjectFillHandler 与全局异常处理完善了数据一致性与用户体验。在此基础上,业务服务只需关注领域逻辑,即可快速实现高质量的数据访问层。 [本节为总结,不直接分析具体文件] ## 附录 - 扩展建议: - 在 CrmSqlInjector 中按需添加更多通用方法(如软删除、逻辑删除) - 在 BaseServiceImpl 中扩展复杂业务校验与补偿逻辑 - 结合缓存策略提升热点数据读取性能 - 最佳实践: - 严格区分 DTO/Param/VO,避免实体泄漏 - 分页查询避免深分页,必要时使用游标或延迟加载 - 批量操作注意内存占用与事务大小平衡 [本节为补充说明,不直接分析具体文件]