Files
his/diagnose_autofill_issue.md

4.6 KiB
Raw Blame History

诊断 MyBatis-Plus 自动填充问题

问题现象

尽管 MybastisColumnsHandler 已经实现并配置了自动填充功能,但 create_bycreate_time 字段仍然没有被正确填充。

可能的原因及解决方案

1. 检查组件扫描配置

确保 MybastisColumnsHandler 类被Spring容器正确管理

@Component  // 确保这个注解存在
public class MybastisColumnsHandler implements MetaObjectHandler {
    // ...
}

2. 检查包扫描路径

在主应用类中确保扫描到了处理器所在的包:

@SpringBootApplication
@MapperScan("com.openhis.*.mapper")  // 确保扫描到你的mapper
@ComponentScan(basePackages = {"com.core", "com.openhis"})  // 确保扫描到处理器
public class OpenHisApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpenHisApplication.class, args);
    }
}

3. 验证实体类配置

确保实体类正确继承了 HisBaseEntity 并且字段上有正确的注解:

@Data
@TableName("adm_practitioner")
public class Practitioner extends HisBaseEntity {
    // 不需要在子类中重复定义 createBy, createTime 等字段
    // 因为它们已在 HisBaseEntity 中定义并带有 @TableField(fill = FieldFill.INSERT)
}

4. 检查安全上下文

自动填充处理器依赖于安全上下文来获取当前用户。确保在执行保存操作时用户已登录:

// 在保存之前,确保用户已登录
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null) {
    // 用户未登录,可能需要手动设置审计字段
}

5. 手动测试自动填充

创建一个简单的测试来验证自动填充是否正常工作:

@SpringBootTest
public class AutoFillTest {
    
    @Autowired
    private PractitionerMapper practitionerMapper;
    
    @Test
    public void testAutoFill() {
        Practitioner practitioner = new Practitioner();
        practitioner.setName("Test Practitioner");
        
        // 检查在保存前字段是否为空
        System.out.println("Before insert - createBy: " + practitioner.getCreateBy());
        System.out.println("Before insert - createTime: " + practitioner.getCreateTime());
        
        // 执行插入操作
        int result = practitionerMapper.insert(practitioner);
        
        // 检查保存后字段是否被填充
        System.out.println("After insert - createBy: " + practitioner.getCreateBy());
        System.out.println("After insert - createTime: " + practitioner.getCreateTime());
        
        assertThat(result).isEqualTo(1);
        assertThat(practitioner.getCreateBy()).isNotNull();
        assertThat(practitioner.getCreateTime()).isNotNull();
    }
}

6. 临时解决方案

如果自动填充仍然不工作,可以在服务层手动设置这些字段:

@Service
public class PractitionerServiceImpl extends ServiceImpl<PractitionerMapper, Practitioner> 
        implements IPractitionerService {
    
    @Override
    public void savePractitioner(Practitioner practitioner) {
        // 手动设置审计字段
        if (practitioner.getCreateBy() == null || practitioner.getCreateBy().isEmpty()) {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (loginUser != null) {
                practitioner.setCreateBy(loginUser.getUsername());
            } else {
                practitioner.setCreateBy("system"); // 默认值
            }
        }
        
        if (practitioner.getCreateTime() == null) {
            practitioner.setCreateTime(new Date());
        }
        
        // 执行保存操作
        this.save(practitioner);
    }
}

7. 检查 MyBatis-Plus 版本兼容性

确保使用的 MyBatis-Plus 版本与自动填充功能兼容。当前项目使用的是 3.5.5 版本,应该支持自动填充功能。

8. 调试自动填充处理器

MybastisColumnsHandler 中添加日志来调试是否被调用:

@Override
public void insertFill(MetaObject metaObject) {
    System.out.println("MybastisColumnsHandler.insertFill() called"); // 调试日志
    
    Date currentTime = new Date();
    this.strictInsertFill(metaObject, "createTime", Date.class, currentTime);
    this.strictInsertFill(metaObject, "create_time", Date.class, currentTime);

    String username = getCurrentUsername();
    System.out.println("Setting createBy to: " + username); // 调试日志
    
    this.strictInsertFill(metaObject, "createBy", String.class, username);
    this.strictInsertFill(metaObject, "create_by", String.class, username);
    
    // ... 其他代码
}

通过以上步骤,应该能够诊断并解决自动填充不工作的问题。