Mybatis 实现动态批量修改

1,451 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

xdm,祝大家节日快乐!!👨‍💻

今天听《路过人间》演唱会Live限定版,爱上了一句歌词。

说来惭愧,人对爱只学会,视死如归。

1.业务需求

如下:

前台传给我一个 documentIdList<UpdateDocumentAnswer> 对象给我。

执行条件:通过这个documentIdList<UpdateDocumentAnswer>中对UpdateDocumentAnswer.id,修改document_answer表的数据。

简单说:就是希望通过一条update语句,根据不同的条件改变多条需要改变的数据。

image-20211024125850091

思考一:

我们先按照我们最简单的思维思考:

即拆成一句一句执行,for循环执行多条 update 语句。

update document_answer set where document_id=#{documentId} and id=#{answer.id}

这样写的话,我们的mapper层接收的参数,应该为:

int patchByDocumentId(@Param("documentId") Long documentId,@Param("answers") UpdateDocumentAnswer answers);

实现是可以实现的,但是因为需要执行多条update语句,效率是真的不敢恭维。

如果大家有尝试过,都会知道,for循环执行sql语句是真的要不得的。一条普通的sql,我们都要优化完再优化,更别说一个方法要执行多条sql语句了。

所有就啥勒??

814268e3ly1fhlpr4j24rj20hs0840ts

推荐大家使用 百度、Bing、Google进行搜索👨‍💻

我们想到过这种问题,大概率别人也会遇上的,搜一搜,确实有答案低。

所以我们接着进入思考二吧。🏍

思考二:

还记得文章前面所说:就是希望通过一条update语句,根据不同的条件改变多条需要改变的数据。

我们直接 搜怎么一条update用不同条件修改多条数据勒

就是会搜到一个下面的这样的sql语句。

update 表名 set1=
	case
		when 条件1 then1
		when 条件2 then2 end,
列2=
	case
		when 条件1 then1
		when 条件2 then2 end,
where 条件

说实话,看到这条语句的那一刻,感觉自己又没有学过mysql了,连crud工程师都算不上(捂脸)。

解释:

我们要 修改列1, 当when 条件1 满足时,则将 列1 修改为 then 后面跟着的 值1,when 条件2 满足,则将列1修改为then 后面跟着的值2。

这样一样,我们就可以执行多条语句了啊。

2.实现

我们将之前的mapper层的接口传入的参数做一下更改。

int patchByDocumentId(@Param("documentId") Long documentId,@Param("answers") List<UpdateDocumentAnswer> answers);

mapper.xml的实现如下:

<update id="patchByDocumentId">
    update document_answer
    <set>
        <trim prefix="template_question_id = case" suffix="end,">
            <foreach collection="answers" item="answer">
                <if test="answer.templateQuestionId != null">
                    when id=#{answer.id} then #{answer.templateQuestionId}
                </if>
            </foreach>
        </trim>


        <trim prefix="answer = case" suffix="end,">
            <foreach collection="answers" item="answer">
                <if test="answer.answer != null">
                    when id=#{answer.id} then #{answer.answer}
                </if>
            </foreach>
        </trim>

        <trim prefix="comments = case" suffix="end,">
            <foreach collection="answers" item="answer">
                <if test="answer.comments != null">
                    when id=#{answer.id} then #{answer.comments}
                </if>
            </foreach>
        </trim>
    </set>
    <where>
        document_id=#{documentId}
        <if test="answers != null">
            and id in
            <foreach collection="answers" separator="," item="answer" open="(" close=")">
                #{answer.id}
            </foreach>
        </if>
    </where>
</update>

生成的sql日志

update document_answer 
SET 
template_question_id = 
	case 
		when id=? then ? 
		when id=? then ? end, 
answer = 
	case 
		when id=? then ? 
		when id=? then ? end, 
comments = 
	case 
		when id=? then ? 
		when id=? then ? end 
WHERE document_id=? and id in ( ? , ? )

换上我们想要的值:

update document_answer 
SET 
template_question_id = 
	case 
		when id=1 then 2 
		when id=1 then 3 end, 
answer = 
	case 
		when id=1 then '内容1' 
		when id=2 then '内容2' end, 
comments = 
	case 
		when id=1 then '评论1' 
		when id=2 then '评论2' end 
WHERE document_id=2 and id in ( 1 , 2 )

执行规则: 上面这种方式,更新的记录的数量取决于list集合的数量,且每条记录中的值和对应记录的ID是一一对应的。

结束了,周日更文一篇。

后语

更惭愧的是,我还没有学会。我们一起加油吧

你好,我是博主宁在春主页

希望本篇文章能让你感到有所收获!!!

我们:待别日相见时,都已有所成

欢迎大家一起讨论问题😁,躺了🛌