首页 > 其他分享 >MyBatisPlus踩坑

MyBatisPlus踩坑

时间:2023-05-26 12:22:46浏览次数:38  
标签:userName metaObject admin setFieldValByName MetaObjectHandler updateBy MyBatisPl

背景

当一个外部系统调用我们一个免登录的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);
    }

}

至此问题成功被解决。

 

标签:userName,metaObject,admin,setFieldValByName,MetaObjectHandler,updateBy,MyBatisPl
From: https://www.cnblogs.com/danielzzz/p/17434348.html

相关文章

  • Springboot+Mybatisplus+ClickHouse集成
    核心依赖引入<dependency><groupId>ru.yandex.clickhouse</groupId><artifactId>clickhouse-jdbc</artifactId><version>0.1.53</version></dependency><!--Mybati......
  • Mybatisplus3.5.1+shardingsphere-jdbc5.1.1分表
    注意使用雪花ID的话,查询ID时候必须使用long类型的ID,不要使用MP自带的默认的Serializable类型。否则会提示分片主键id数据类型和分片算法不匹配Inlineshardingalgorithmsexpressionxxxandshardingcolumnxxnotmatch错误。。。导入依赖<!--sharding-jdbc分库分表-->......
  • 分享一下mybatisPlus新代码生成器3.5.1以上
    pom引入:有MP了就不要再引入mybatis了,会出bug的<!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</......
  • MybatisPlus中LamdaQueryWrapper 与 QueryWrapper的使用及区别
    一、QueryWrapper的使用;比如有一张表trolley_itme,需要通过device_id查询出符合条件的所有数据(返回List集合);1、QueryWrapper的最基础的使用方式是这样的:必须写清楚具体的字段名称(即有硬编码的嫌疑)//查询条件的构造器:QueryWrapper<TrolleyItme>queryWrapper=new QueryWra......
  • 使用mybatisplus分页插件,设置了每页容量和页数但还是获取的全部数据(已解决)
    注意观察mybatisplus的查询语句,分页插件正确配置后,在查询时会使用limit限制查询的数量(如下图) 但是如果没配置好就是没有limit这个限制,只要加上配置文件或者确认自己的配置正确即可,配置参考如下博客springboot(二)整合mybatisplus+分页插件+代码生成springboot(二)整合mybat......
  • MyBatisPlus
    MyBatisPlus今日目标基于MyBatisPlus完成标准Dao的增删改查功能掌握MyBatisPlus中的分页及条件查询构建掌握主键ID的生成策略了解MyBatisPlus的代码生成器1,MyBatisPlus入门案例与简介这一节我们来学习下MyBatisPlus的入门案例与简介,这个和其他课程都不太一样,其他的课程都......
  • MybatisPlus高级特性之SimpleQuery工具类
    1、是很么?SimpleQuery可以对selectList查询后的结果使用Stream流进行操作,使其可以返回指定的结果,简洁了api的调用2、怎么玩?案例演示(1)list操作/***list(LambdaQueryWrapper<E>wrapper,SFunction<E,A>sFunction,Consumer<E>...peeks)*参数说明:*p......
  • MybatisPlus高级特性之ActiveRecord模式
    1、是什么?ActiveRecord是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表;而模型类的一个实例对应表中的一行记录。ActiveRecord一直广受解释型动态语言(PHP、Ruby等)的喜爱,通过围绕一个数据对象进行CRUD操作。而Java作为准静态(编译型)语言,对于ActiveRec......
  • MybatisPlus 模糊查询数组中的所有字符串
     List<IcvDevice>deviceList=icvDeviceMapper.selectList(Wrappers.<IcvDevice>query().or(qw->pidList.forEach(sbbh->qw.like("sbbh",sbbh))).eq("sssblx&q......
  • PageHelper和MybatisPlus的分页插件冲突
    分页插件优先使用的PageHelper的拦截器,所以当两种分页插件同时使用时PageHelper没有影响,而MybatisPlus的分页失效。解决方法:1、只用MyBatis+PageHelper或只用MybatisPlus;2、同时使用的话MybatisPlus构造查询语句,然后分页的业务交给PageHelper。同时使用的话不能配置MybatisPlus......