# 通用实体类
**本文引用的文件**
- [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)
- [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)
- [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)
- [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向“通用实体类”的设计与使用,重点阐述 BaseEntity 与 OwnedEntity 的设计模式、字段定义、继承关系与使用方法。文档覆盖以下核心能力:
- 基础字段的自动填充机制(创建时间、更新时间、逻辑删除等)
- 数据权限控制字段(数据可见性、归属者过滤)
- 审计字段(创建人、更新人等)
- 实体扩展指南与最佳实践示例
通过统一的基类抽象,业务实体可快速获得一致的持久化行为、安全访问与审计追踪能力,降低重复代码并提升一致性。
## 项目结构
通用实体类位于 crm-base 模块的 domain.entity 包中,配合配置与工具类实现自动填充与数据权限控制。关键位置如下:
- 实体基类:BaseEntity、OwnedEntity
- 自动填充处理器:MetaObjectFillHandler
- MyBatis-Plus 集成配置:MybatisPlusConfig、CrmSqlInjector
- 数据权限注解与辅助:DataScope、DataScopeHelper、DataVisibilityContext、SecurityUtils、LoginUser
- 服务层基类:BaseServiceImpl、IBaseService
- 测试用例:DataScopeIntegrationTest
```mermaid
graph TB
subgraph "基础模块 crm-base"
BE["BaseEntity"]
OE["OwnedEntity"]
MFH["MetaObjectFillHandler"]
MPC["MybatisPlusConfig"]
CSI["CrmSqlInjector"]
DS_ANN["DataScope 注解"]
DSH["DataScopeHelper"]
DVC["DataVisibilityContext"]
SEC["SecurityUtils"]
LU["LoginUser"]
BSI["BaseServiceImpl"]
IBS["IBaseService"]
end
BE --> |被继承| OE
MFH --> |注册到| MPC
CSI --> |注入MP增强| MPC
DSH --> |读取上下文| DVC
DSH --> |获取当前用户| SEC
SEC --> |持有| LU
BSI --> |使用| BE
BSI --> |使用| OE
```
图表来源
- [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)
- [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)
- [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)
章节来源
- [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)
- [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)
- [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)
## 核心组件
- BaseEntity:提供所有实体的公共基础字段与行为,通常包括主键、创建/更新时间、创建/更新人、逻辑删除标记等。通过自动填充机制在插入或更新时自动设置审计字段。
- OwnedEntity:在 BaseEntity 基础上增加数据所有权相关字段(如所属部门、所属租户、数据所有者ID等),用于数据权限控制与隔离。
二者共同构成领域模型的“横切关注点”统一入口,使业务实体无需重复编写通用逻辑。
章节来源
- [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)
## 架构总览
下图展示了从请求进入、权限解析、SQL 注入增强到实体自动填充的整体流程。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Controller as "控制器"
participant Service as "业务服务(BaseServiceImpl)"
participant MP as "MyBatis-Plus"
participant Fill as "自动填充处理器(MetaObjectFillHandler)"
participant DB as "数据库"
Client->>Controller : "发起CRUD请求"
Controller->>Service : "调用服务方法"
Service->>MP : "执行insert/update/select"
MP->>Fill : "触发自动填充(插入/更新)"
Fill-->>MP : "回填审计字段"
MP->>DB : "执行SQL"
DB-->>MP : "返回结果"
MP-->>Service : "返回实体集合/对象"
Service-->>Controller : "返回响应"
Controller-->>Client : "返回JSON"
```
图表来源
- [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)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
## 详细组件分析
### BaseEntity 设计
- 职责:定义所有实体的通用字段与默认行为,确保全系统一致的数据模型规范。
- 典型字段类别:
- 标识与状态:主键、逻辑删除标记、状态枚举等
- 审计字段:创建时间、更新时间、创建人、更新人
- 其他通用属性:备注、排序等(视具体实现而定)
- 自动填充:通过 MetaObjectFillHandler 在插入/更新时自动填充审计字段;逻辑删除由 MyBatis-Plus 插件增强。
- 扩展建议:新增通用字段应优先放入 BaseEntity,避免在各业务实体中重复定义。
```mermaid
classDiagram
class BaseEntity {
+主键
+创建时间
+更新时间
+创建人
+更新人
+逻辑删除标记
+通用方法()
}
```
图表来源
- [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)
章节来源
- [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 之上叠加数据所有权与可见性控制所需字段,支撑多租户、多部门、个人数据隔离等场景。
- 典型字段类别:
- 数据所有者ID、所属部门ID、所属租户ID等
- 数据可见性级别(私有、部门、公司、自定义范围)
- 与数据权限体系联动:结合 DataScope 注解与 DataScopeHelper,在查询时动态拼接 WHERE 条件,实现行级数据权限控制。
- 扩展建议:若业务需要更细粒度的数据隔离(如项目维度、客户维度),可在 OwnedEntity 上扩展相应字段并在权限策略中处理。
```mermaid
classDiagram
class BaseEntity
class OwnedEntity {
+数据所有者ID
+所属部门ID
+所属租户ID
+数据可见性级别
+权限相关方法()
}
OwnedEntity --|> BaseEntity : "继承"
```
图表来源
- [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)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
### 自动填充机制
- 触发时机:插入与更新操作前,由 MyBatis-Plus 拦截并调用 MetaObjectFillHandler。
- 填充内容:创建时间、更新时间、创建人、更新人等审计字段;可根据需要扩展更多字段。
- 实现要点:
- 在 MybatisPlusConfig 中注册填充处理器
- 在 MetaObjectFillHandler 中根据当前登录用户信息填充审计字段
- 逻辑删除由 CrmSqlInjector 注入全局 SQL 片段,保证软删除一致性
```mermaid
flowchart TD
Start(["开始"]) --> CheckOp["判断操作类型
插入/更新"]
CheckOp --> |插入| FillCreate["填充创建时间/创建人"]
CheckOp --> |更新| FillUpdate["填充更新时间/更新人"]
FillCreate --> Next["继续执行"]
FillUpdate --> Next
Next --> 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)
- [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)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
### 数据权限控制
- 注解驱动:通过 @DataScope 标注接口或方法,声明数据可见性级别与过滤规则。
- 上下文管理:DataVisibilityContext 维护当前请求的数据可见性上下文;SecurityUtils 提供当前登录用户信息。
- 辅助工具:DataScopeHelper 负责解析注解、合并权限条件,并在查询时生效。
- 典型流程:
1) 请求进入,解析当前用户与角色
2) 根据 @DataScope 确定数据范围
3) 生成并注入 WHERE 条件
4) 执行查询,仅返回有权限的数据
```mermaid
sequenceDiagram
participant C as "调用方"
participant S as "服务方法(@DataScope)"
participant H as "DataScopeHelper"
participant V as "DataVisibilityContext"
participant U as "SecurityUtils"
participant M as "Mapper/MP"
C->>S : "调用带@DataScope的方法"
S->>U : "获取当前用户"
S->>V : "设置数据可见性上下文"
S->>H : "解析注解并生成过滤条件"
H-->>M : "注入WHERE条件"
M-->>S : "返回受限数据集"
S-->>C : "返回结果"
```
图表来源
- [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)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.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)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
### 服务层基类与使用方式
- BaseServiceImpl:封装常用 CRUD 操作,统一使用 BaseEntity/OwenedEntity 的能力,减少样板代码。
- IBaseService:定义通用服务接口,便于各业务服务继承复用。
- 使用建议:
- 业务实体继承 BaseEntity 或 OwnedEntity
- 业务服务继承 BaseServiceImpl,实现 IBaseService
- 在需要数据权限控制的接口上添加 @DataScope 注解
```mermaid
classDiagram
class IBaseService
class BaseServiceImpl {
+分页查询()
+新增()
+修改()
+删除()
+批量操作()
}
class 业务Service {
+业务方法()
}
IBaseService <|.. BaseServiceImpl
BaseServiceImpl <|-- 业务Service
```
图表来源
- [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)
章节来源
- [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)
### 实体扩展指南与最佳实践
- 继承选择:
- 仅需基础审计与软删除:继承 BaseEntity
- 需要数据权限与隔离:继承 OwnedEntity
- 字段命名与类型:
- 审计字段保持统一命名与类型,便于自动填充与序列化
- 枚举字段建议使用强类型枚举,避免魔法值
- 自动填充注意事项:
- 确保当前登录用户上下文已正确设置
- 避免在业务层手动覆盖审计字段,以免破坏一致性
- 数据权限最佳实践:
- 在查询入口统一使用 @DataScope,避免遗漏
- 复杂权限规则通过 DataScopeHelper 扩展,不要硬编码 WHERE 条件
- 测试验证:
- 参考 DataScopeIntegrationTest 进行端到端数据权限验证
章节来源
- [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)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java)
## 依赖关系分析
- 实体层依赖:
- BaseEntity 为所有实体提供基础能力
- OwnedEntity 依赖 BaseEntity,并引入数据权限字段
- 配置与工具依赖:
- MybatisPlusConfig 注册自动填充处理器与 SQL 注入器
- MetaObjectFillHandler 依赖 SecurityUtils 获取当前用户
- DataScopeHelper 依赖 DataVisibilityContext 与 SecurityUtils 解析权限
- 服务层依赖:
- BaseServiceImpl 基于 MyBatis-Plus 与实体基类提供通用 CRUD
```mermaid
graph LR
BE["BaseEntity"] --> OE["OwnedEntity"]
MPC["MybatisPlusConfig"] --> MFH["MetaObjectFillHandler"]
MPC --> CSI["CrmSqlInjector"]
MFH --> SEC["SecurityUtils"]
DSH["DataScopeHelper"] --> DVC["DataVisibilityContext"]
DSH --> SEC
BSI["BaseServiceImpl"] --> BE
BSI --> OE
```
图表来源
- [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)
- [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)
- [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)
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
## 性能考虑
- 自动填充开销极低,仅在插入/更新时触发,对整体性能影响可忽略
- 数据权限过滤会在 SQL 层面注入 WHERE 条件,建议在高频查询字段建立合适索引
- 避免在自动填充处理器中进行耗时操作(如远程调用),必要时异步化或缓存
- 合理使用分页与只读字段,减少不必要的数据传输
## 故障排查指南
- 审计字段未填充:
- 检查是否继承 BaseEntity/OwenedEntity
- 确认 MybatisPlusConfig 已注册 MetaObjectFillHandler
- 确认当前登录用户上下文已设置
- 数据权限不生效:
- 确认接口或方法添加了 @DataScope
- 检查 DataVisibilityContext 是否正确设置
- 查看生成的 SQL 是否包含权限过滤条件
- 逻辑删除异常:
- 确认 CrmSqlInjector 已启用
- 检查实体是否正确使用逻辑删除字段
章节来源
- [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)
- [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)
## 结论
BaseEntity 与 OwnedEntity 为系统提供了统一的实体基线,结合自动填充与数据权限控制,显著降低了重复开发成本,提升了数据一致性与安全性。遵循本文的扩展指南与最佳实践,可在保证质量的前提下快速构建稳定可靠的业务实体与服务。
## 附录
- 常见字段说明:
- 主键:唯一标识实体
- 创建时间/更新时间:审计追踪
- 创建人/更新人:责任追溯
- 逻辑删除标记:软删除支持
- 数据所有者/部门/租户:数据隔离与权限控制
- 推荐实践清单:
- 所有实体继承 BaseEntity 或 OwnedEntity
- 使用 @DataScope 标注需权限控制的查询
- 不在业务层直接修改审计字段
- 为高频查询字段建立索引
- 通过单元测试验证权限与填充行为