批量插入
<!--批量增加測(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í)

第二種方式耗時(shí)

更新100條
第一種

第二種

更新1000條
第一種

第二種

更新10000條
第一種

第二種

結(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ù)效率,安全方面綜合考慮,選擇適合的很重要。