Mybatis批量插入、更新

批量插入

<!--批量增加測(cè)試-->
    <insert id="insertList" parameterType="java.util.List">
        insert into t_enterprise_water_ele (<include refid="Base_Column_List"/>)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (
            #{item.waterEleId,jdbcType=VARCHAR},
            #{item.enterpriseId,jdbcType=VARCHAR},
            #{item.enterpriseUscc,jdbcType=VARCHAR},
            #{item.enterpriseName,jdbcType=VARCHAR},
            #{item.yearmonth,jdbcType=VARCHAR},
            #{item.waterSize,jdbcType=DECIMAL},
            #{item.waterAmount,jdbcType=VARCHAR},
            #{item.eleSize,jdbcType=DOUBLE},
            #{item.eleAmount,jdbcType=VARCHAR},
            #{item.status,jdbcType=INTEGER},
            #{item.operator,jdbcType=VARCHAR},
            #{item.operateTime,jdbcType=TIMESTAMP}
            )
        </foreach>
    </insert>

對(duì)于foreach標(biāo)簽的解釋參考了網(wǎng)上的資料,具體如下:
foreach的主要用在構(gòu)建in條件中,它可以在SQL語(yǔ)句中進(jìn)行迭代一個(gè)集合。
foreach元素的屬性主要有 item,index,collection,open,separator,close。
item表示集合中每一個(gè)元素進(jìn)行迭代時(shí)的別名
index指定一個(gè)名字,用于表示在迭代過(guò)程中,每次迭代到的位置
open表示該語(yǔ)句以什么開(kāi)始
separator表示在每次進(jìn)行迭代之間以什么符號(hào)作為分隔 符
close表示以什么結(jié)束
在使用foreach的時(shí)候最關(guān)鍵的也是最容易出錯(cuò)的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該屬性的值是不一樣的,主要有一下3種情況:
1.如果傳入的是單參數(shù)且參數(shù)類型是一個(gè)List的時(shí)候,collection屬性值為list
2.如果傳入的是單參數(shù)且參數(shù)類型是一個(gè)array數(shù)組的時(shí)候,collection的屬性值為array
3.如果傳入的參數(shù)是多個(gè)的時(shí)候,我們就需要把它們封裝成一個(gè)Map了,當(dāng)然單參數(shù)也可以封裝成map

批量更新

更新單個(gè)字段

根據(jù)goodsId查詢出的多條記錄,只更新 NODE_ID 字段

<!-- 方式一 -->
  <update id="updateByBatch" parameterType="java.util.List">
    update t_goods
    set NODE_ID=
    <foreach collection="list" item="item" index="index"
             separator=" " open="case" close="end">
      when GOODS_ID=#{item.goodsId} then #{item.nodeId}
    </foreach>
    where GOODS_ID in
    <foreach collection="list" index="index" item="item"
             separator="," open="(" close=")">
      #{item.goodsId,jdbcType=BIGINT}
    </foreach>
  </update>

<!-- 方式二 -->
<update id="updateByBatch" parameterType="java.util.List">
    UPDATE
    t_goods
    SET NODE_ID = CASE
    <foreach collection="list" item="item" index="index">
      WHEN GOODS_ID = #{item.goodsId} THEN #{item.nodeId}
    </foreach>
    END
    WHERE GOODS_ID IN
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
      #{item.goodsId}
    </foreach>
  </update>

更新多個(gè)字段

根據(jù)userId 查詢出的多條記錄,更新 STATUS ,OPERATE_TIME , OPERATOR 字段

<update id="updateBatch" parameterType="java.util.List">
    update t_user
    <trim prefix="set" suffixOverrides=",">
        <trim prefix="STATUS =case" suffix="end,">
            <foreach collection="list" item="i" index="index">
                <if test="i.status!=null">
                    when USER_ID=#{i.userId} then #{i.status}
                </if>
            </foreach>
        </trim>
        <trim prefix=" OPERATE_TIME =case" suffix="end,">
            <foreach collection="list" item="i" index="index">
                <if test="i.operateTime!=null">
                    when USER_ID=#{i.userId} then #{i.operateTime}
                </if>
            </foreach>
        </trim>

        <trim prefix="OPERATOR =case" suffix="end," >
            <foreach collection="list" item="i" index="index">
                <if test="i.operator!=null">
                    when USER_ID=#{i.userId} then #{i.operator}
                </if>
            </foreach>
        </trim>
    </trim>
    where
    <foreach collection="list" separator="or" item="i" index="index" >
        USER_ID=#{i.userId}
    </foreach>
</update>

性能對(duì)比

注意第一種方法要想成功,需要在db鏈接url后面帶一個(gè)參數(shù) &allowMultiQueries=true

即: jdbc:mysql://localhost:3306/mysqlTest?characterEncoding=utf-8&allowMultiQueries=true

<!-- 批量更新第一種方法,通過(guò)接收傳進(jìn)來(lái)的參數(shù)list進(jìn)行循環(huán)著組裝sql -->
    <update id="batchUpdate" parameterType="java.util.List">
        <foreach collection="list" separator=";" item="cus">
            update t_customer set
            c_name = #{cus.name},
            c_age = #{cus.age},
            c_sex = #{cus.sex},
            c_ceroNo = #{cus.ceroNo},
            c_ceroType = #{cus.ceroType}
            where id = #{cus.id}
        </foreach>
    </update>


<!-- 批量更新第二種方法,通過(guò) case when語(yǔ)句變相的進(jìn)行批量更新 -->
    <update id="batchUpdateCaseWhen" parameterType="java.util.List">
        update t_customer
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="c_name =case" suffix="end,">
                <foreach collection="list" item="cus">
                    <if test="cus.name!=null">
                        when id=#{cus.id} then #{cus.name}
                    </if>
                </foreach>
            </trim>
            <trim prefix="c_age =case" suffix="end,">
                <foreach collection="list" item="cus">
                    <if test="cus.age!=null">
                        when id=#{cus.id} then #{cus.age}
                    </if>
                </foreach>
            </trim>
            <trim prefix="c_sex =case" suffix="end,">
                <foreach collection="list" item="cus">
                    <if test="cus.sex!=null">
                        when id=#{cus.id} then #{cus.sex}
                    </if>
                </foreach>
            </trim>
            <trim prefix="c_ceroNo =case" suffix="end,">
                <foreach collection="list" item="cus">
                    <if test="cus.ceroNo!=null">
                        when id=#{cus.id} then #{cus.ceroNo}
                    </if>
                </foreach>
            </trim>
            <trim prefix="c_ceroType =case" suffix="end,">
                <foreach collection="list" item="cus">
                    <if test="cus.ceroType!=null">
                        when id=#{cus.id} then #{cus.ceroType}
                    </if>
                </foreach>
            </trim>
        </trim>
        <where>
            <foreach collection="list" separator="or" item="cus">
                id = #{cus.id}
            </foreach>
        </where>
    </update>
更新10條

第一種方式耗時(shí)

image.png

第二種方式耗時(shí)

image.png
更新100條

第一種

image.png

第二種

image.png
更新1000條

第一種

image.png

第二種

image.png
更新10000條

第一種

image.png

第二種

image.png

結(jié)果可以看出,兩種方式進(jìn)行批量更新,效率已經(jīng)不在一個(gè)數(shù)量級(jí)了。case when明顯的慢的多。

第一種效率其實(shí)相當(dāng)高的,因?yàn)樗鼉H僅有一個(gè)循環(huán)體,只不過(guò)最后update語(yǔ)句比較多,量大了就有可能造成sql阻塞。

第二種雖然最后只會(huì)有一條更新語(yǔ)句,但是xml中的循環(huán)體有點(diǎn)多,每一個(gè)case when 都要循環(huán)一遍list集合,所以大批量拼sql的時(shí)候會(huì)比較慢,所以效率問(wèn)題嚴(yán)重。使用的時(shí)候建議分批插入。

根據(jù)效率,安全方面綜合考慮,選擇適合的很重要。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容