Backup local changes before resolving remote repository issue

This commit is contained in:
2026-01-27 10:05:25 +08:00
parent 11c2758289
commit 86bca03b04
29 changed files with 2626 additions and 126 deletions

113
audit_field_solution.md Normal file
View File

@@ -0,0 +1,113 @@
# 关于数据库审计字段create_by, create_time等的处理方案
## 问题描述
在使用OpenHIS系统时可能会遇到如下错误
```
org.postgresql.util.PSQLException: ERROR: null value in column "create_by" of relation "adm_practitioner" violates not-null constraint
```
## 问题分析
1. 数据库表中的审计字段如create_by, create_time设置了NOT NULL约束
2. 应用程序层面使用了MyBatis-Plus的自动填充功能来设置这些字段
3. 当自动填充机制失效时,就会出现违反非空约束的错误
## 解决方案
### 方案一:修复自动填充机制(推荐)
系统已经实现了自动填充机制,位于 `MybastisColumnsHandler.java`
```java
// 设置数据新增时候的,字段自动赋值规则
@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 = "system";
try {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null) {
username = loginUser.getUsername();
}
} catch (Exception ignored) {
}
// 使用 fillStrategy 确保即使字段为 null 也会被填充
this.strictInsertFill(metaObject, "createBy", String.class, username);
this.strictInsertFill(metaObject, "create_by", String.class, username);
// 如果 strictInsertFill 没有生效,使用 setFieldValByName 强制设置
if (metaObject.hasGetter("createBy") && metaObject.getValue("createBy") == null) {
this.setFieldValByName("createBy", username, metaObject);
}
if (metaObject.hasGetter("create_by") && metaObject.getValue("create_by") == null) {
this.setFieldValByName("create_by", username, metaObject);
}
...
}
```
确保所有实体类都继承自 `HisBaseEntity``BaseEntity`,这样就能自动获得审计字段。
### 方案二:移除数据库约束(谨慎使用)
如果确实需要允许审计字段为NULL可以移除数据库约束
```sql
-- 移除 adm_practitioner 表中 create_by 列的 NOT NULL 约束
ALTER TABLE "public"."adm_practitioner"
ALTER COLUMN "create_by" DROP NOT NULL;
-- 同样处理 create_time 列(如果需要)
ALTER TABLE "public"."adm_practitioner"
ALTER COLUMN "create_time" DROP NOT NULL;
```
### 方案三:批量修复所有表的约束
如果多个表都存在这个问题,可以使用以下脚本:
```sql
-- 为所有表的审计字段移除NOT NULL约束
-- 注意:执行前请备份数据库!
-- 1. 检查所有包含审计字段的表
SELECT
table_name,
column_name,
is_nullable
FROM
information_schema.columns
WHERE
column_name IN ('create_by', 'create_time', 'update_by', 'update_time')
AND table_schema = 'public'
AND is_nullable = 'NO'; -- NO 表示 NOT NULL 约束
-- 2. 根据需要移除特定表的约束
-- 示例移除多个表的create_by约束
ALTER TABLE "public"."adm_practitioner" ALTER COLUMN "create_by" DROP NOT NULL;
ALTER TABLE "public"."adm_patient" ALTER COLUMN "create_by" DROP NOT NULL;
-- 添加更多表的处理...
```
## 最佳实践
### 1. 确保实体类继承基础类
所有实体类应继承 `HisBaseEntity``BaseEntity`
```java
@Data
@TableName("adm_practitioner")
public class Practitioner extends HisBaseEntity {
// 其他字段...
}
```
### 2. 检查安全上下文
确保在保存数据时有有效的安全上下文,这样自动填充处理器才能获取到当前用户信息。
### 3. 验证自动填充配置
确保 `MybastisColumnsHandler` 在Spring容器中被正确注册使用@Component注解)。
## 总结
- 推荐保持数据库中的NOT NULL约束确保数据完整性
- 依赖MyBatis-Plus的自动填充机制来设置审计字段
- 确保所有实体类继承基础实体类
- 在必要时才考虑移除数据库约束