You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

17 KiB

基础服务层

**本文引用的文件** - [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/*:实体基类、结果封装、枚举、异常等
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
  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java
  • Result.java
  • PageResult.java
  • BaseEntity.java
  • OwnedEntity.java

章节来源

  • IBaseService.java
  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java
  • Result.java
  • PageResult.java
  • BaseEntity.java
  • OwnedEntity.java

核心组件

  • IBaseService:定义通用CRUD、分页查询、批量操作的统一接口契约,供各业务服务继承或组合使用。
  • BaseServiceImpl:基于 MyBatis Plus 的 ServiceImpl 提供默认实现,封装事务、参数校验、异常转换、分页与批量方法。
  • CrmBaseMapper:扩展 MyBatis Plus 的 BaseMapper,提供统一的查询构造、动态条件、批量操作等能力。
  • MybatisPlusConfig + CrmSqlInjector:注册自定义SQL注入器,为Mapper注入通用方法(如动态条件查询、批量插入更新)。
  • MetaObjectFillHandler:自动填充审计字段(创建时间、更新时间、创建人等),保证数据一致性。
  • GlobalExceptionHandlerAdvice:统一异常捕获与响应封装,将业务异常转换为标准 Result 返回。

章节来源

  • IBaseService.java
  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java

架构总览

下图展示了从控制器到服务层再到数据访问层的调用链,以及基础服务层在其中的作用。

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
  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java

详细组件分析

IBaseService 接口设计

  • 职责:定义通用CRUD、分页查询、批量操作的方法签名,确保各业务服务具备一致的数据访问能力。
  • 典型能力:
    • 单条/批量新增、修改、删除
    • 按ID获取、条件查询、分页查询
    • 批量更新(支持部分字段)
    • 返回统一结果类型(Result/PageResult)
  • 设计要点:
    • 泛型约束实体类型,便于类型安全
    • 输入参数与输出结果采用DTO/Param/VO分离,避免泄露内部模型
    • 分页查询返回 PageResult,包含数据列表与分页信息

章节来源

  • IBaseService.java
  • Result.java
  • PageResult.java

BaseServiceImpl 实现细节

  • 事务管理:
    • 关键写操作(新增、修改、删除、批量)包裹在事务中,保证原子性
    • 读操作通常非事务或只读事务,减少锁竞争
  • 数据验证:
    • 入参非空校验、业务规则校验(如唯一性检查)
    • 结合实体注解与自定义校验器,统一错误提示
  • 异常处理:
    • 捕获并转换底层异常为业务异常
    • 通过全局异常处理器统一封装为 Result
  • 分页与批量:
    • 分页查询使用 MyBatis Plus 的分页插件,配合动态条件构建
    • 批量操作优先使用批处理器,降低往返开销
  • 审计字段填充:
    • 借助 MetaObjectFillHandler 自动填充创建/更新时间、操作人等
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
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java

章节来源

  • BaseServiceImpl.java
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java

CrmBaseMapper 与 MyBatis Plus 扩展

  • 扩展点:
    • 继承 MyBatis Plus 的 BaseMapper,提供通用CRUD能力
    • 通过自定义 SQL 注入器注入动态条件查询、批量方法
  • 动态条件构建:
    • 支持多条件组合(等于、模糊、范围、IN等)
    • 可结合实体属性生成 WHERE 片段,避免手写SQL
  • 批量操作:
    • 批量插入/更新,利用数据库特性优化性能
    • 支持 ON DUPLICATE KEY UPDATE 或 MERGE 语义(由注入器决定)
  • 分页查询:
    • 与分页插件集成,自动拼接 LIMIT/OFFSET 或等效语法
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
  • MybatisPlusConfig.java
  • CrmSqlInjector.java

章节来源

  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java

实体基类与审计字段

  • BaseEntity:
    • 定义通用字段(如主键、状态、删除标记等)
    • 与填充处理器协作,自动维护审计字段
  • OwnedEntity:
    • 在 BaseEntity 基础上增加数据权限相关字段(如所属部门、归属人)
    • 配合数据可见性上下文,实现行级权限控制
classDiagram
class BaseEntity {
+id
+createTime
+updateTime
+creator
+updater
}
class OwnedEntity {
+ownerId
+deptId
}
BaseEntity <|-- OwnedEntity

图表来源

  • BaseEntity.java
  • OwnedEntity.java

章节来源

  • BaseEntity.java
  • OwnedEntity.java

依赖关系分析

  • 组件耦合:
    • BaseServiceImpl 依赖 CrmBaseMapper 完成数据访问
    • MybatisPlusConfig 负责装配 CrmSqlInjector 与分页插件
    • MetaObjectFillHandler 与实体基类协作完成审计字段填充
    • GlobalExceptionHandlerAdvice 统一捕获异常并封装为 Result
  • 外部依赖:
    • MyBatis Plus:ORM框架、分页插件、SQL注入机制
    • 数据库驱动:具体SQL方言由注入器适配
graph LR
Impl["BaseServiceImpl"] --> Mapper["CrmBaseMapper"]
Mapper --> MPConf["MybatisPlusConfig"]
MPConf --> SQLI["CrmSqlInjector"]
Impl --> Fill["MetaObjectFillHandler"]
Impl --> Ex["GlobalExceptionHandlerAdvice"]
Impl --> Res["Result/PageResult"]

图表来源

  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java
  • Result.java
  • PageResult.java

章节来源

  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • MetaObjectFillHandler.java
  • GlobalExceptionHandlerAdvice.java
  • Result.java
  • PageResult.java

性能考量

  • 分页查询:
    • 使用分页插件避免全表扫描,合理设置 page/size
    • 复杂条件查询建议建立合适索引
  • 批量操作:
    • 优先使用批量插入/更新,减少网络往返
    • 大批量数据分片提交,避免单次事务过大
  • 事务边界:
    • 缩小事务范围,避免长事务导致锁竞争
    • 读多写少场景尽量使用只读事务
  • 填充与校验:
    • 审计字段填充在写入前完成,避免额外更新
    • 校验失败尽早返回,减少无效DB交互

[本节为通用指导,不直接分析具体文件]

故障排查指南

  • 常见异常:
    • 参数校验失败:检查入参非空与业务规则
    • 事务回滚:查看日志中的异常堆栈,定位失败SQL或约束冲突
    • 分页异常:确认分页参数合法性与排序字段存在
  • 调试建议:
    • 开启 MyBatis SQL 日志,观察实际执行的SQL
    • 使用全局异常处理器返回的 Result 快速定位错误码与消息
    • 针对批量操作,逐步缩小批次大小定位问题

章节来源

  • GlobalExceptionHandlerAdvice.java
  • BaseServiceImpl.java

结论

基础服务层通过 IBaseService 与 BaseServiceImpl 提供了稳定、一致的CRUD与分页、批量能力;CrmBaseMapper 与自定义 SQL 注入器增强了动态条件与批量处理能力;MetaObjectFillHandler 与全局异常处理完善了数据一致性与用户体验。在此基础上,业务服务只需关注领域逻辑,即可快速实现高质量的数据访问层。

[本节为总结,不直接分析具体文件]

附录

  • 扩展建议:
    • 在 CrmSqlInjector 中按需添加更多通用方法(如软删除、逻辑删除)
    • 在 BaseServiceImpl 中扩展复杂业务校验与补偿逻辑
    • 结合缓存策略提升热点数据读取性能
  • 最佳实践:
    • 严格区分 DTO/Param/VO,避免实体泄漏
    • 分页查询避免深分页,必要时使用游标或延迟加载
    • 批量操作注意内存占用与事务大小平衡

[本节为补充说明,不直接分析具体文件]