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.
 
 
 
 
 

20 KiB

数据访问架构

**本文引用的文件** - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.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) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [AuthUserMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/AuthUserMapper.java) - [SysDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysDeptMapper.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [application.yml](file://crm-app/src/main/resources/application.yml)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向数据层开发者,系统化阐述CRM系统基于MyBatis-Plus的ORM数据访问架构与最佳实践。内容覆盖:

  • 通用Mapper基类与Service抽象的设计与使用
  • 分页查询、批量插入、主键生成、自动填充等能力
  • 数据库连接池配置、事务管理策略、SQL注入防护
  • 实体设计规范、字段映射规则、关联查询处理
  • 数据访问层次结构与优化策略

项目结构

本项目采用多模块分层设计,数据访问相关代码集中在基础模块与业务模块中:

  • 基础模块(crm-base):提供通用Mapper、Service实现、MyBatis-Plus配置、安全与数据权限工具、统一结果与分页封装等
  • 认证模块(crm-auth):具体业务实体、Mapper接口、Service实现示例
  • 应用入口(crm-app):应用启动与全局配置
graph TB
subgraph "应用层"
APP["应用启动<br/>crm-app"]
end
subgraph "业务模块"
AUTH["认证模块<br/>crm-auth"]
end
subgraph "基础模块"
BASE["基础模块<br/>crm-base"]
end
DB["数据库"]
APP --> AUTH
AUTH --> BASE
BASE --> DB

图表来源

  • application.yml
  • MybatisPlusConfig.java

章节来源

  • application.yml
  • MybatisPlusConfig.java

核心组件

  • CrmBaseMapper:通用Mapper基类,扩展常用CRUD与分页能力,供业务Mapper继承
  • BaseServiceImpl:通用Service实现,封装标准CRUD、分页查询、批量操作等
  • IBaseService:通用Service接口定义,约束业务Service的统一方法集
  • MybatisPlusConfig:MyBatis-Plus全局配置(分页插件、自动填充、主键策略、SQL注入拦截等)
  • MetaObjectFillHandler:自动填充处理器(创建时间、更新时间、创建人等)
  • CustomIdGenerator/SnowflakeIdWorker:分布式雪花ID生成器
  • InsertBatchOnDuplicateKeyUpdate:批量插入去重更新策略
  • BaseEntity/OwnedEntity:实体基类,统一审计字段与数据归属字段
  • PageResult/PageConverter:分页结果封装与转换工具
  • DataScope注解与DataScopeHelper/DataVisibilityContext/SecurityUtils:数据权限与可见性控制

章节来源

  • CrmBaseMapper.java
  • BaseServiceImpl.java
  • IBaseService.java
  • MybatisPlusConfig.java
  • MetaObjectFillHandler.java
  • CustomIdGenerator.java
  • SnowflakeIdWorker.java
  • InsertBatchOnDuplicateKeyUpdate.java
  • BaseEntity.java
  • OwnedEntity.java
  • PageResult.java
  • PageConverter.java
  • DataScope.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • SecurityUtils.java

架构总览

数据访问层遵循“Controller → Service → Mapper → MyBatis-Plus → 数据库”的分层模式,通过通用基类与配置实现标准化开发。

classDiagram
class CrmBaseMapper {
+通用CRUD方法()
+分页查询()
+批量操作()
}
class BaseServiceImpl {
+新增()
+修改()
+删除()
+查询单条()
+分页查询()
+批量保存()
}
class IBaseService {
<<interface>>
+新增()
+修改()
+删除()
+查询单条()
+分页查询()
+批量保存()
}
class AuthUserMapper
class SysDeptMapper
class AuthUserServiceImpl
class SysDeptServiceImpl
AuthUserMapper --|> CrmBaseMapper : "继承"
SysDeptMapper --|> CrmBaseMapper : "继承"
AuthUserServiceImpl ..|> IBaseService : "实现"
SysDeptServiceImpl ..|> IBaseService : "实现"
BaseServiceImpl <|-- AuthUserServiceImpl : "复用"
BaseServiceImpl <|-- SysDeptServiceImpl : "复用"

图表来源

  • CrmBaseMapper.java
  • BaseServiceImpl.java
  • IBaseService.java
  • AuthUserMapper.java
  • SysDeptMapper.java
  • AuthUserServiceImpl.java
  • SysDeptServiceImpl.java

详细组件分析

通用Mapper基类:CrmBaseMapper

  • 职责:为所有业务Mapper提供统一的CRUD与分页能力,减少样板代码
  • 关键能力:
    • 标准增删改查方法
    • 分页查询支持(结合MyBatis-Plus分页插件)
    • 批量操作(如批量插入、批量更新)
    • 条件构造器友好扩展
  • 使用方式:业务Mapper直接继承该基类,无需重复定义基础方法

章节来源

  • CrmBaseMapper.java

通用Service实现:BaseServiceImpl

  • 职责:封装通用的Service逻辑,包括事务边界、参数校验、分页转换、异常处理等
  • 关键能力:
    • 单条/批量新增、修改、删除
    • 按主键查询与条件查询
    • 分页查询(返回统一PageResult)
    • 与CrmBaseMapper协作完成数据访问
  • 事务策略:在需要原子性的方法上声明事务,确保一致性

章节来源

  • BaseServiceImpl.java
  • IBaseService.java

分页查询实现

  • 分页插件:通过MyBatis-Plus分页插件启用分页功能
  • 分页对象:使用Page对象进行分页查询,返回结果转换为PageResult
  • 转换工具:PageConverter负责将框架分页对象转换为业务分页结果
sequenceDiagram
participant Client as "调用方"
participant Service as "BaseServiceImpl"
participant Mapper as "CrmBaseMapper"
participant MP as "MyBatis-Plus分页插件"
participant DB as "数据库"
Client->>Service : 请求分页查询
Service->>Service : 构建查询条件
Service->>MP : 创建分页对象并设置页码/大小
Service->>Mapper : 执行分页查询
Mapper->>MP : 拦截并改写SQL
MP->>DB : 执行分页SQL
DB-->>MP : 返回分页数据
MP-->>Mapper : 返回分页结果
Mapper-->>Service : 返回分页结果
Service->>Service : 转换为PageResult
Service-->>Client : 返回分页响应

图表来源

  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • PageConverter.java
  • MybatisPlusConfig.java

章节来源

  • PageConverter.java
  • PageResult.java
  • MybatisPlusConfig.java

主键生成与自动填充

  • 主键策略:自定义雪花ID生成器,保证分布式环境下唯一性与有序性
  • 自动填充:通过MetaObjectFillHandler在插入/更新时自动填充审计字段(如创建时间、更新时间、创建人等)
flowchart TD
Start(["实体持久化"]) --> CheckId{"是否已设置主键?"}
CheckId --> |否| GenId["雪花ID生成器生成主键"]
CheckId --> |是| FillAudit["自动填充审计字段"]
GenId --> FillAudit
FillAudit --> Save["写入数据库"]
Save --> End(["完成"])

图表来源

  • CustomIdGenerator.java
  • SnowflakeIdWorker.java
  • MetaObjectFillHandler.java

章节来源

  • CustomIdGenerator.java
  • SnowflakeIdWorker.java
  • MetaObjectFillHandler.java

批量插入与冲突处理

  • 批量插入:通过InsertBatchOnDuplicateKeyUpdate实现高效批量插入
  • 冲突策略:根据业务需求配置“存在即更新”或忽略冲突,避免重复数据

章节来源

  • InsertBatchOnDuplicateKeyUpdate.java

实体设计规范与字段映射

  • BaseEntity:统一审计字段(如id、createTime、updateTime、creator、updater等)
  • OwnedEntity:数据归属字段(如deptId、ownerId等),配合数据权限控制
  • 字段映射:遵循MyBatis-Plus默认命名规则,必要时使用注解指定映射
erDiagram
BASE_ENTITY {
bigint id PK
datetime create_time
datetime update_time
string creator
string updater
}
OWNED_ENTITY {
bigint dept_id
bigint owner_id
}
BASE_ENTITY ||--o{ OWNED_ENTITY : "继承"

图表来源

  • BaseEntity.java
  • OwnedEntity.java

章节来源

  • BaseEntity.java
  • OwnedEntity.java

数据权限与可见性控制

  • DataScope注解:用于标记方法的数据范围
  • DataScopeHelper:解析数据范围条件,动态拼接SQL
  • DataVisibilityContext:维护当前请求的数据可见性上下文
  • SecurityUtils:获取当前登录用户信息,辅助权限判断
sequenceDiagram
participant Controller as "控制器"
participant Service as "业务Service"
participant Helper as "DataScopeHelper"
participant Context as "DataVisibilityContext"
participant DB as "数据库"
Controller->>Service : 调用带@DataScope的方法
Service->>Context : 读取当前用户可见范围
Service->>Helper : 解析数据范围条件
Helper-->>Service : 返回WHERE条件片段
Service->>DB : 执行带数据范围的查询
DB-->>Service : 返回受限数据
Service-->>Controller : 返回结果

图表来源

  • DataScope.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • SecurityUtils.java

章节来源

  • DataScope.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • SecurityUtils.java

业务Mapper与Service示例

  • AuthUserMapper/SysDeptMapper:继承CrmBaseMapper,获得通用CRUD能力
  • AuthUserServiceImpl/SysDeptServiceImpl:继承BaseServiceImpl,复用通用Service逻辑

章节来源

  • AuthUserMapper.java
  • SysDeptMapper.java
  • AuthUserServiceImpl.java
  • SysDeptServiceImpl.java

依赖关系分析

  • MyBatis-Plus:提供ORM能力、分页插件、自动填充、主键策略等
  • 数据源与连接池:由Spring Boot自动装配,可通过配置文件调整连接池参数
  • 安全与权限:SecurityUtils与DataScope相关组件协同工作,保障数据安全
graph TB
MP["MyBatis-Plus"] --> Config["MybatisPlusConfig"]
Config --> Fill["MetaObjectFillHandler"]
Config --> IdGen["CustomIdGenerator"]
Config --> Batch["InsertBatchOnDuplicateKeyUpdate"]
Base["BaseServiceImpl"] --> Mapper["CrmBaseMapper"]
Mapper --> MP
Security["SecurityUtils"] --> Scope["DataScopeHelper"]
Scope --> Context["DataVisibilityContext"]

图表来源

  • MybatisPlusConfig.java
  • MetaObjectFillHandler.java
  • CustomIdGenerator.java
  • InsertBatchOnDuplicateKeyUpdate.java
  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • SecurityUtils.java
  • DataScopeHelper.java
  • DataVisibilityContext.java

章节来源

  • MybatisPlusConfig.java
  • BaseServiceImpl.java
  • CrmBaseMapper.java
  • SecurityUtils.java
  • DataScopeHelper.java
  • DataVisibilityContext.java

性能考虑

  • 分页查询:优先使用分页插件,避免全量加载;合理设置页大小
  • 批量操作:使用批量插入/更新接口,减少网络往返
  • 索引优化:为高频查询字段建立合适索引,避免全表扫描
  • SQL监控:开启SQL日志与慢查询分析,定位性能瓶颈
  • 连接池调优:根据并发与负载调整连接池大小、超时与回收策略

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

故障排查指南

  • 分页无效:检查分页插件是否注册、请求参数是否正确
  • 自动填充未生效:确认MetaObjectFillHandler已配置且字段匹配
  • 主键重复:检查雪花ID生成器配置与节点ID分配
  • 数据权限异常:查看DataScope注解与方法签名、上下文是否正确设置
  • 事务不回滚:确认异常类型与事务传播行为是否符合预期

章节来源

  • MybatisPlusConfig.java
  • MetaObjectFillHandler.java
  • CustomIdGenerator.java
  • DataScope.java
  • DataScopeHelper.java

结论

通过CrmBaseMapper与BaseServiceImpl的抽象设计,结合MyBatis-Plus的强大能力,CRM系统在数据访问层实现了高度标准化与可复用。配合数据权限、自动填充、批量操作与分页机制,开发者可以专注于业务逻辑,提升开发与维护效率。建议严格遵循实体规范、合理使用索引与事务,持续优化SQL与连接池配置,以保障系统稳定与高性能。

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

附录

  • 实体设计建议:统一继承BaseEntity/OwnedEntity,明确字段语义与映射规则
  • 查询优化建议:优先使用条件构造器,避免N+1查询,合理使用JOIN与子查询
  • 事务管理建议:在Service层声明事务,明确边界与传播行为
  • 安全与合规:始终使用参数化查询,防止SQL注入;敏感数据脱敏与加密存储

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