Backup local changes before resolving remote repository issue
This commit is contained in:
202
audit_field_best_practices.md
Normal file
202
audit_field_best_practices.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# OpenHIS 系统审计字段填充最佳实践
|
||||
|
||||
## 概述
|
||||
本文档介绍如何在 OpenHIS 系统中确保所有实体的审计字段(create_by、create_time、update_by、update_time)能够正确自动填充。
|
||||
|
||||
## 自动填充机制
|
||||
|
||||
### 1. 基础实体类
|
||||
所有需要审计字段的实体类都应该继承自 `HisBaseEntity`:
|
||||
|
||||
```java
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
|
||||
@Data
|
||||
@TableName("adm_practitioner")
|
||||
public class Practitioner extends HisBaseEntity {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
// 其他业务字段...
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 自动填充处理器
|
||||
系统使用 `MybastisColumnsHandler` 来自动填充审计字段:
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class MybastisColumnsHandler implements MetaObjectHandler {
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
// 填充创建时间和创建人
|
||||
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
|
||||
this.strictInsertFill(metaObject, "create_time", Date.class, new Date());
|
||||
|
||||
String username = getCurrentUsername(); // 获取当前用户名
|
||||
this.strictInsertFill(metaObject, "createBy", String.class, username);
|
||||
this.strictInsertFill(metaObject, "create_by", String.class, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
// 填充更新时间和更新人
|
||||
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
|
||||
this.strictUpdateFill(metaObject, "update_time", Date.class, new Date());
|
||||
|
||||
String username = getCurrentUsername(); // 获取当前用户名
|
||||
this.strictUpdateFill(metaObject, "updateBy", String.class, username);
|
||||
this.strictUpdateFill(metaObject, "update_by", String.class, username);
|
||||
}
|
||||
|
||||
private String getCurrentUsername() {
|
||||
String username = "system";
|
||||
try {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (loginUser != null) {
|
||||
username = loginUser.getUsername();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return username;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 确保自动填充正常工作的要点
|
||||
|
||||
### 1. 检查实体类继承关系
|
||||
确保所有实体类都正确继承了 `HisBaseEntity`:
|
||||
|
||||
```java
|
||||
// 正确的做法
|
||||
public class Practitioner extends HisBaseEntity { ... }
|
||||
|
||||
// 如果不能继承 HisBaseEntity,则需要手动添加审计字段
|
||||
public class CustomEntity {
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
private Date updateTime;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 验证安全上下文
|
||||
确保在执行数据库操作时有有效的安全上下文:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class PractitionerService {
|
||||
public void savePractitioner(Practitioner practitioner) {
|
||||
// 确保调用此方法时用户已登录
|
||||
// SecurityUtils.getLoginUser() 应该能返回有效的 LoginUser 对象
|
||||
|
||||
// MyBatis-Plus 会在保存时自动调用 MybastisColumnsHandler
|
||||
practitionerMapper.insert(practitioner);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 检查配置
|
||||
确保自动填充处理器被正确配置:
|
||||
|
||||
```yaml
|
||||
# application.yml
|
||||
mybatis-plus:
|
||||
global-config:
|
||||
db-config:
|
||||
# 其他配置...
|
||||
configuration:
|
||||
# 其他配置...
|
||||
```
|
||||
|
||||
### 4. 手动填充(特殊情况)
|
||||
在某些特殊情况下,如果自动填充不工作,可以手动设置:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class PractitionerService {
|
||||
public void savePractitionerManually(Practitioner practitioner) {
|
||||
// 手动设置审计字段
|
||||
Date now = new Date();
|
||||
String currentUser = getCurrentUsername();
|
||||
|
||||
practitioner.setCreateTime(now);
|
||||
practitioner.setCreateBy(currentUser);
|
||||
practitioner.setUpdateTime(now);
|
||||
practitioner.setUpdateBy(currentUser);
|
||||
|
||||
practitionerMapper.insert(practitioner);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 常见问题及解决方案
|
||||
|
||||
### 问题1:自动填充不生效
|
||||
**原因:**
|
||||
- 实体类没有继承 `HisBaseEntity`
|
||||
- `MybastisColumnsHandler` 没有被Spring管理(缺少@Component注解)
|
||||
- 没有有效的安全上下文
|
||||
|
||||
**解决方案:**
|
||||
- 确保实体类继承 `HisBaseEntity`
|
||||
- 检查 `MybastisColumnsHandler` 是否有 `@Component` 注解
|
||||
- 确保在调用保存方法时用户已登录
|
||||
|
||||
### 问题2:获取不到当前用户
|
||||
**原因:**
|
||||
- 用户未登录
|
||||
- 安全上下文配置错误
|
||||
|
||||
**解决方案:**
|
||||
- 在调用保存方法前确保用户已登录
|
||||
- 检查安全配置是否正确
|
||||
|
||||
### 问题3:批量操作时审计字段未填充
|
||||
**原因:**
|
||||
- 批量操作可能绕过了自动填充机制
|
||||
|
||||
**解决方案:**
|
||||
- 对于批量操作,手动设置审计字段
|
||||
- 或者使用 MyBatis-Plus 的批量操作方法,确保它们支持自动填充
|
||||
|
||||
## 测试验证
|
||||
|
||||
创建一个简单的测试来验证自动填充是否正常工作:
|
||||
|
||||
```java
|
||||
@SpringBootTest
|
||||
public class AuditFieldTest {
|
||||
@Autowired
|
||||
private PractitionerMapper practitionerMapper;
|
||||
|
||||
@Test
|
||||
public void testAuditFieldsAutoFill() {
|
||||
Practitioner practitioner = new Practitioner();
|
||||
practitioner.setName("Test Practitioner");
|
||||
|
||||
// 保存实体
|
||||
practitionerMapper.insert(practitioner);
|
||||
|
||||
// 验证审计字段是否被正确填充
|
||||
assertThat(practitioner.getCreateBy()).isNotNull();
|
||||
assertThat(practitioner.getCreateTime()).isNotNull();
|
||||
|
||||
// 清理测试数据
|
||||
practitionerMapper.deleteById(practitioner.getId());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 总结
|
||||
通过遵循以上最佳实践,可以确保 OpenHIS 系统中的所有实体在保存时都能正确填充审计字段,避免因缺少这些字段而引发的数据库约束错误。
|
||||
Reference in New Issue
Block a user