# 通用实体类 **本文引用的文件** - [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 标注需权限控制的查询 - 不在业务层直接修改审计字段 - 为高频查询字段建立索引 - 通过单元测试验证权限与填充行为