MyBatisPlus踩坑

发布时间 2023-05-26 12:13:34作者: danielzzz

背景

当一个外部系统调用我们一个免登录的API接口,在我们数据库去保存或更新一条数据时,库表中的创建人和更新人字段不是正确的值。

但是代码层面我们是有正确的设置创建人和更新人,查询sql日志发现我们设置的值统一被替换为“admin”了。

这个时候才明白为什么另一个接口中在保存完数据后,还有一个单独更新创建人的更新操作。

但是这样也是有问题的。在更新操作的时候,创建人是可以被正确的修改,但是更新人还是会被替换为“admin”的。

找BUG

百度后发现应该是 MetaObjectHandler 类的对数据做出的更改。

MetaObjectHandler简介

MyBatis-Plus的MetaObjectHandler是一个拦截器,用于处理实体字段的自动填充。当我们使用MyBatis-Plus进行数据库操作时,有些字段的值是需要在插入或更新操作时动态生成的,比如创建时间、修改时间、创建者、修改者等等。这时我们就可以使用MetaObjectHandler拦截器来实现自动填充。

MetaObjectHandler拦截器主要提供以下两个方法:

  • insertFill:用于插入操作时的字段填充;
  • updateFill:用于更新操作时的字段填充。

这些方法会在执行插入或更新操作时自动调用,从而完成字段填充的功能。我们可以通过继承MetaObjectHandler类并重写这些方法来达到自定义填充的目的。需要注意的是,除了自动填充之外,MetaObjectHandler还可以实现一些其他的功能,比如逻辑删除等等。

 

然后在项目中找到如下代码:

@Configuration
public class MyBatisConfig implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        String userName = "admin";
        try {
            userName = SecurityUtils.getUsername();
        } catch (Exception e) {
        }

        this.setFieldValByName("createBy", userName, metaObject);
        this.setFieldValByName("updateBy", userName, metaObject);
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        String userName = "admin";
        try {
            userName = SecurityUtils.getUsername();
        } catch (Exception e) {
        }
        
        this.setFieldValByName("updateBy", userName, metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

}

查看代码可以发现,在外部系统免登录的情况下,createBy 字段和 updateBy 字段 都会默认填充为 “admin”;这就解释即使我们手动设置了这些值,在插入数据时还是被替换成“admin”了。

 

修复BUG

我们需要对上述代码做些优化:

@Configuration
public class MyBatisConfig implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        String userName = "admin";
        try {
            userName = SecurityUtils.getUsername();
        } catch (Exception e) {
        }
        // createBy和updateBy字段为空时,才自动填充创建人和修改人的值
        Object createBy = getFieldValByName("createBy", metaObject);
        Object updateBy = getFieldValByName("updateBy", metaObject);
        if (createBy == null) {
            this.setFieldValByName("createBy", userName, metaObject);
        }
        if (updateBy == null) {
            this.setFieldValByName("updateBy", userName, metaObject);
        }
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        String userName = "admin";
        try {
            userName = SecurityUtils.getUsername();
        } catch (Exception e) {
        }
        Object updateBy = getFieldValByName("updateBy", metaObject);
        if (updateBy == null) {
            this.setFieldValByName("updateBy", userName, metaObject);
        }
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

}

至此问题成功被解决。