当前位置: 代码网 > it编程>编程语言>Java > mybatis-plus调用update方法时,自动填充字段不生效问题及解决

mybatis-plus调用update方法时,自动填充字段不生效问题及解决

2024年06月10日 Java 我要评论
项目场景做定时任务,查询出数据后,将他发往mq队列,如果搭建集群相同的数据就会执行多次,所以使用乐观锁解决,同时需要更改更新时间一列,直接使用mybatisplus的公共字段填充和乐观锁问题描述配置好

项目场景

做定时任务,查询出数据后,将他发往mq队列,如果搭建集群相同的数据就会执行多次,所以使用乐观锁解决,同时需要更改更新时间一列,直接使用mybatisplus的公共字段填充和乐观锁

问题描述

配置好mp的乐观锁和公共字段填充后,执行update语句,正常应该是

update tb_task set update_time=?,version=? where (version = ? and id = ?)

结果变成了

update tb_task set where (version = ? and id = ?)

因为除了这两个字段没有其他需要修改的字段所以直接就报错了,这么一看肯定是乐观锁和公共字段填充都失效了啊。

@scheduled(cron = "0 0/1 * * * ?")
    public void addcoursetask(){
        //查询1分钟之前的数据
        list<tbtask> list = tbtaskservice.findbeforeminutelist();
        for (tbtask tbtask : list) {
            //根据id version修改
            lambdaupdatewrapper<tbtask> wrapper = new lambdaupdatewrapper<>();
            wrapper.eq(tbtask::getid,tbtask.getid());
                    //.set(tbtask::getversion,tbtask.getversion()+1);
            //数据库中的乐观锁, 防止集群下的订单,重复向mq中发送数据
            if (tbtaskservice.update(wrapper)) {
                string mqexchange = tbtask.getmqexchange();
                string mqroutingkey = tbtask.getmqroutingkey();
                //向mq发送消息
                rabbittemplate.convertandsend(mqexchange, mqroutingkey, json.tojsonstring(tbtask));

            }


        }
    }

原因分析

检查了几遍确定mp的乐观锁和公共字段填充都没有问题

乐观锁

1.配置乐观锁插件(mp是3.5.1的)

@configuration
@mapperscan("com.xly.mapper") //扫描mapper接口所在包
public class mybatisplusconfig {

    @bean
    //配置分页插件
    public mybatisplusinterceptor mybatisplusinterceptor(){
        mybatisplusinterceptor interceptor = new mybatisplusinterceptor();
        //分页
        interceptor.addinnerinterceptor(new paginationinnerinterceptor(dbtype.mysql));
        //乐观锁
        interceptor.addinnerinterceptor(new optimisticlockerinnerinterceptor());
        return interceptor;

    }
}

2.字段上打注解

@tablefield(value = "version")
    @version
    private integer version;

公共字段填充

1.实现metaobjecthandler的公共填充类

@component
public class mymetaobjecthandler implements metaobjecthandler {
    //mp执行添加操作,这个方法执行
    @override
    public void insertfill(metaobject metaobject) {
        metaobject.setvalue("createtime",new date());
        metaobject.setvalue("updatetime",new date());
    }

    //mp执行修改操作,这个方法执行
    @override
    public void updatefill(metaobject metaobject) {
        metaobject.setvalue("updatetime",new date());
    }
}

2.在字段上添加fill属性

@tablefield(value = "create_time",fill = fieldfill.insert)
    private date createtime;
    @tablefield(value = "update_time",fill = fieldfill.insert_update)
    private date updatetime;

经过查找资料后发现使用boolean update(wrapper updatewrapper)这个方法,自动填充会失效

大概原理就是boolean update(wrapper updatewrapper)的底层实现为:

default boolean update(wrapper<t> updatewrapper) {
        return this.update((object)null, updatewrapper);
    }

而属性自动填充需要从第一个参数获取object实体类,自动填充的核心方法:populatekeys中会判断

if (null == tableinfo) {
            /* 不处理 */
            return parameterobject;
        }

tableinfo就是获取的实体类对象,所以导致属性自动填充失效。

解决方案

我使用的是上面文章建议的方案一,也是最简单的方式:

使用update的重载方法

boolean update(t entity, wrapper updatewrapper)

修改后的代码如下:

@scheduled(cron = "0 0/1 * * * ?")
    public void addcoursetask(){
        //查询1分钟之前的数据
        list<tbtask> list = tbtaskservice.findbeforeminutelist();
        for (tbtask tbtask : list) {
            //根据id version修改
            lambdaupdatewrapper<tbtask> wrapper = new lambdaupdatewrapper<>();
            wrapper.eq(tbtask::getid,tbtask.getid());
                    //.set(tbtask::getversion,tbtask.getversion()+1);
            //数据库中的乐观锁, 防止集群下的订单,重复向mq中发送数据
            if (tbtaskservice.update(tbtask,wrapper)) {
                string mqexchange = tbtask.getmqexchange();
                string mqroutingkey = tbtask.getmqroutingkey();
                //向mq发送消息
                rabbittemplate.convertandsend(mqexchange, mqroutingkey, json.tojsonstring(tbtask));

            }


        }
    }

执行sql语句:

update tb_task
set create_time=?, update_time=?, delete_time=?, task_type=?, mq_exchange=?, mq_routingkey=?, request_body=?, status=?, version=? where (version = ? and id = ?)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com