202 lines
5.8 KiB
Markdown
202 lines
5.8 KiB
Markdown
# 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 系统中的所有实体在保存时都能正确填充审计字段,避免因缺少这些字段而引发的数据库约束错误。 |