# 通用实体类
**本文引用的文件**
- [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)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.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)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向“通用实体类”的设计与使用,重点说明:
- BaseEntity 作为所有实体的基类,提供统一的公共字段(如 ID、创建时间、更新时间等)及自动填充策略。
- OwnedEntity 在 BaseEntity 基础上增加数据所有权控制机制(数据所有者字段与权限继承),并配合数据可见性上下文实现细粒度访问控制。
- 自动填充机制与审计字段管理由 MyBatis-Plus 的元对象处理器统一处理,确保一致性、可维护性与高性能。
- 数据可见性控制通过注解与拦截器协作,结合登录用户上下文进行动态过滤。
- 提供实体继承的最佳实践与自定义扩展方法建议,帮助业务模块快速复用与扩展。
## 项目结构
通用实体类位于基础模块 crm-base 中,围绕实体定义、自动填充、数据权限与可见性形成完整闭环。下图展示了与实体相关的核心文件及其职责分工。
```mermaid
graph TB
subgraph "基础实体"
BE["BaseEntity
公共字段与审计"]
OE["OwnedEntity
数据所有权与权限继承"]
end
subgraph "自动填充与配置"
MOF["MetaObjectFillHandler
自动填充处理器"]
MPC["MybatisPlusConfig
注册填充处理器"]
CSI["CrmSqlInjector
SQL注入增强"]
end
subgraph "数据权限与可见性"
DS_A["DataScope
数据范围注解"]
DO_A["DataOwnership
数据所有权注解"]
DSH["DataScopeHelper
权限辅助工具"]
DVC["DataVisibilityContext
可见性上下文"]
SU["SecurityUtils
安全工具"]
LU["LoginUser
登录用户信息"]
end
BE --> OE
MOF --> BE
MOF --> OE
MPC --> MOF
DSH --> DVC
DSH --> SU
DSH --> LU
DS_A --> DSH
DO_A --> DSH
```
图表来源
- [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)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.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)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.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)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.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)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
## 核心组件
- BaseEntity:所有实体的根类,集中定义公共字段(如主键 ID、创建时间、更新时间等)与审计相关能力,并通过自动填充保证字段一致性。
- OwnedEntity:在 BaseEntity 之上引入数据所有权字段与权限继承逻辑,用于实现“谁拥有、谁能看、谁能改”的数据隔离与可见性控制。
- MetaObjectFillHandler:基于 MyBatis-Plus 的元对象处理器,负责在插入、更新等生命周期自动填充审计字段(如创建人、创建时间、更新人、更新时间)。
- DataScope 与 DataOwnership:分别用于声明数据范围与数据所有权,配合 DataScopeHelper 完成运行时权限计算与 SQL 条件注入。
- DataVisibilityContext 与 SecurityUtils:封装当前请求的可见性上下文与安全上下文,为权限判断提供稳定入口。
- CrmSqlInjector:对 MyBatis-Plus 的 SQL 生成进行增强,将数据权限条件注入到查询语句中。
章节来源
- [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)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
## 架构总览
下图展示从请求进入、权限解析、数据可见性判断到 SQL 注入与结果返回的整体流程,体现 BaseEntity/OwendEntity 与权限体系的协同工作方式。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Controller as "控制器"
participant Service as "服务层(BaseServiceImpl)"
participant Mapper as "数据访问层"
participant Injector as "CrmSqlInjector"
participant Helper as "DataScopeHelper"
participant Context as "DataVisibilityContext"
participant Fill as "MetaObjectFillHandler"
Client->>Controller : "发起CRUD请求"
Controller->>Service : "调用业务方法"
Service->>Helper : "解析数据权限(注解/上下文)"
Helper->>Context : "获取可见性上下文"
Context-->>Helper : "返回可见性规则"
Service->>Mapper : "执行查询/写入"
Mapper->>Injector : "生成/增强SQL"
Injector-->>Mapper : "注入数据权限条件"
Mapper-->>Service : "返回结果集"
Service-->>Controller : "返回业务结果"
Note over Fill,Service : "插入/更新时自动填充审计字段"
```
图表来源
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.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)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
## 详细组件分析
### BaseEntity:公共字段与审计基类
- 职责定位
- 统一定义所有实体共享的基础字段(如主键 ID、创建时间、更新时间等)。
- 与自动填充处理器配合,确保审计字段在插入、更新时自动赋值,避免业务代码重复处理。
- 设计要点
- 字段命名与类型需与数据库表结构一致,便于 ORM 映射。
- 审计字段应仅由框架自动填充,不建议在业务层手动覆盖,以保证一致性。
- 最佳实践
- 所有业务实体均应继承 BaseEntity,以获得一致的审计能力。
- 如需扩展新的审计字段,优先通过 MetaObjectFillHandler 扩展,而非修改每个实体。
章节来源
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
### OwnedEntity:数据所有权与权限继承
- 职责定位
- 在 BaseEntity 基础上增加“数据所有者”字段,用于标识数据归属。
- 提供权限继承机制:子实体可继承父实体的所有权或按自身规则覆盖,从而实现层级化数据隔离。
- 权限模型
- 数据所有者字段通常与登录用户关联,支持多租户或多组织场景下的数据隔离。
- 结合 DataOwnership 注解与 DataScopeHelper,可在查询时动态注入“仅查看本人/本部门/全公司”等条件。
- 数据可见性控制
- 通过 DataVisibilityContext 维护当前请求的可见性范围(如个人、部门、企业、自定义范围)。
- 查询前由 DataScopeHelper 根据注解与上下文生成 WHERE 条件,确保数据不可越权访问。
```mermaid
classDiagram
class BaseEntity {
+id
+createTime
+updateTime
+...
}
class OwnedEntity {
+ownerId
+inheritPermission()
+applyVisibilityFilter()
}
class DataScopeHelper {
+resolveScope()
+buildCondition()
}
class DataVisibilityContext {
+getCurrentScope()
+setScope(scope)
}
class SecurityUtils {
+getLoginUser()
+hasPermission(entity)
}
OwnedEntity --|> BaseEntity : "继承"
DataScopeHelper --> DataVisibilityContext : "读取可见性"
DataScopeHelper --> SecurityUtils : "读取登录用户"
OwnedEntity --> DataScopeHelper : "使用权限辅助"
```
图表来源
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.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)
章节来源
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.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)
### 自动填充机制与审计字段管理
- 触发时机
- 插入:自动填充创建时间、创建人等字段。
- 更新:自动填充更新时间、更新人等字段。
- 实现方式
- 通过 MetaObjectFillHandler 实现 MyBatis-Plus 的元对象处理器接口,在插入/更新回调中设置字段值。
- 由 MybatisPlusConfig 注册该处理器,使其全局生效。
- 注意事项
- 若业务需要覆盖默认填充行为,应在填充处理器中增加分支逻辑,而不是在业务层直接赋值。
- 对于软删除、状态变更等审计需求,可通过扩展填充处理器新增字段填充策略。
```mermaid
flowchart TD
Start(["开始"]) --> Op{"操作类型"}
Op --> |插入| InsertFill["填充创建时间/创建人"]
Op --> |更新| UpdateFill["填充更新时间/更新人"]
InsertFill --> Save["保存实体"]
UpdateFill --> Save
Save --> End(["结束"])
```
图表来源
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.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)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
### 数据可见性控制与权限继承
- 注解驱动
- DataScope:声明数据范围(如个人、部门、企业、自定义),由 DataScopeHelper 解析并生成 SQL 条件。
- DataOwnership:声明数据所有权规则,结合 OwnedEntity 的 owner 字段进行权限继承与校验。
- 上下文与工具
- DataVisibilityContext:维护当前请求的可见性范围,支持线程隔离。
- SecurityUtils:提供获取登录用户、权限判断等能力。
- 执行流程
- 在 Service 层调用 Mapper 前,先通过 DataScopeHelper 解析注解与上下文,生成 WHERE 条件。
- CrmSqlInjector 将条件注入到最终 SQL,确保查询结果符合权限要求。
```mermaid
sequenceDiagram
participant Svc as "服务层"
participant Helper as "DataScopeHelper"
participant Ctx as "DataVisibilityContext"
participant Sec as "SecurityUtils"
participant Inject as "CrmSqlInjector"
Svc->>Helper : "解析@DataScope/@DataOwnership"
Helper->>Ctx : "获取可见性范围"
Ctx-->>Helper : "返回范围"
Helper->>Sec : "读取登录用户信息"
Sec-->>Helper : "返回用户与角色"
Helper-->>Svc : "返回SQL条件片段"
Svc->>Inject : "执行查询"
Inject-->>Svc : "注入权限条件后的SQL"
```
图表来源
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
章节来源
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
### 实体继承最佳实践与自定义扩展
- 继承建议
- 所有业务实体统一继承 BaseEntity,确保审计字段一致。
- 涉及数据隔离的业务实体继承 OwnedEntity,并在 Service 层使用 @DataScope/@DataOwnership 声明权限规则。
- 扩展点
- 新增审计字段:在 MetaObjectFillHandler 中增加填充逻辑,避免侵入业务代码。
- 新增权限维度:在 DataScopeHelper 中扩展解析逻辑,并在 CrmSqlInjector 中注入对应 SQL 条件。
- 自定义可见性规则:在 DataVisibilityContext 中扩展范围类型与转换逻辑。
- 常见陷阱
- 不要在业务层直接修改审计字段,以免破坏一致性。
- 权限注解必须与服务方法一一对应,避免遗漏导致越权。
- 复杂查询需确保 CrmSqlInjector 能正确注入条件,必要时提供自定义 SQL 注入策略。
章节来源
- [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)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
## 依赖关系分析
- 实体层依赖
- OwnedEntity 依赖 BaseEntity,获得公共字段与审计能力。
- 权限与可见性
- DataScopeHelper 依赖 DataVisibilityContext 与 SecurityUtils,用于解析权限与获取用户信息。
- CrmSqlInjector 依赖 MyBatis-Plus 的 SQL 生成机制,注入权限条件。
- 自动填充
- MetaObjectFillHandler 被 MybatisPlusConfig 注册,全局生效于所有实体插入/更新操作。
```mermaid
graph LR
OwnedEntity --> BaseEntity
DataScopeHelper --> DataVisibilityContext
DataScopeHelper --> SecurityUtils
CrmSqlInjector --> MyBatisPlus["MyBatis-Plus"]
MetaObjectFillHandler --> MyBatisPlus
MybatisPlusConfig --> MetaObjectFillHandler
```
图表来源
- [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)
- [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)
- [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)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.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)
- [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)
- [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)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
## 性能考量
- 自动填充开销极小,仅在插入/更新时触发,不影响查询路径。
- 数据权限条件在 SQL 层注入,避免应用层二次过滤,减少内存与 CPU 消耗。
- 建议在大数据量查询时合理使用分页与索引,确保权限条件能命中索引。
- 避免在 Service 层进行大量集合运算,尽量将过滤下推到数据库层。
[本节为通用指导,不直接分析具体文件]
## 故障排查指南
- 审计字段未填充
- 检查 MetaObjectFillHandler 是否正确注册;确认实体继承 BaseEntity。
- 确认插入/更新操作是否经过 MyBatis-Plus 的持久化流程。
- 数据权限无效
- 检查 @DataScope/@DataOwnership 注解是否加在服务方法上。
- 确认 DataVisibilityContext 中的可见性范围是否正确设置。
- 查看生成的 SQL 是否包含权限条件,必要时启用 SQL 日志。
- 越权访问
- 核对 SecurityUtils 获取的登录用户信息是否准确。
- 检查 DataScopeHelper 的权限解析逻辑是否符合业务规则。
章节来源
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.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)
## 结论
- BaseEntity 与 OwnedEntity 构成了统一的实体基线,前者提供审计与公共字段,后者提供数据所有权与权限继承。
- 通过 MetaObjectFillHandler 与 CrmSqlInjector,实现了“无侵入”的自动填充与权限注入,提升开发效率与系统安全性。
- 建议在业务设计中严格遵循继承规范与注解约定,充分利用框架提供的扩展点,降低维护成本与出错概率。
[本节为总结性内容,不直接分析具体文件]
## 附录
- 常用扩展点清单
- 新增审计字段:在 MetaObjectFillHandler 中扩展填充逻辑。
- 新增权限维度:在 DataScopeHelper 中扩展解析与 SQL 注入。
- 自定义可见性规则:在 DataVisibilityContext 中扩展范围类型。
- 参考服务基类
- BaseServiceImpl 提供通用的 CRUD 能力,可与 BaseEntity/OwendEntity 无缝协作。
章节来源
- [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)