日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Mybatis 批量操作8种实现总结

發(fā)布時間:2024/3/12 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mybatis 批量操作8种实现总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

批量新增

1.方式一(常用)

<!-- 批量新增--> <insert id="batchSave" parameterType="java.util.List">INSERT INTO lp_user_test_batch(id,user_id,user_name,user_age,type,create_time,update_time)VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.id,jdbcType=BIGINT},#{item.userId,jdbcType=VARCHAR},#{item.userName,jdbcType=VARCHAR},#{item.userAge,jdbcType=INTEGER},#{item.type,jdbcType=INTEGER},#{item.createTime,jdbcType=TIMESTAMP},#{item.updateTime,jdbcType=TIMESTAMP})</foreach> </insert>

測試結(jié)果

數(shù)量耗時
10001469ms
20002534ms
30002613ms
40003549ms
50004733ms
80005761ms
100006055ms

2.方式二

批量新增或更新方式
注:需要給唯一主鍵添加唯一索引,update才會生效

<!-- 批量新增或更新--> <insert id="batchSaveOrUpdate" parameterType="java.util.List">INSERT INTO lp_user_test_batch(id,user_id,user_name,user_age,type,create_time,update_time)VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.id,jdbcType=BIGINT},#{item.userId,jdbcType=VARCHAR},#{item.userName,jdbcType=VARCHAR},#{item.userAge,jdbcType=INTEGER},#{item.type,jdbcType=INTEGER},#{item.createTime,jdbcType=TIMESTAMP},#{item.updateTime,jdbcType=TIMESTAMP})</foreach>ON DUPLICATE KEY UPDATEuser_name = VALUES(user_name),user_age = VALUES(user_age),type = VALUES(type),update_time = VALUES(update_time) </insert>

測試結(jié)果

數(shù)量耗時
10001692ms
20002346ms
30003249ms
40003443ms
50003999ms
80006460ms
100007053ms

3.方式三

單條sql+批量方式的SqlSession

<insert id="insert" >INSERT INTO lp_user_test_batch(id,user_id,user_name,user_age,type,create_time,update_time)values(#{id,jdbcType=BIGINT},#{userId,jdbcType=VARCHAR},#{userName,jdbcType=VARCHAR},#{userAge,jdbcType=INTEGER},#{type,jdbcType=INTEGER},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP}) </insert> @Resource(name = "sqlSessionFactory") private SqlSessionFactory sqlSessionFactory;/*** 利用 MyBatis 批處理特性,批量提交*/ public void batchInsert(List<UserTestBatchDO> testBatchDAOList) {//集合非空if (CollectionUtils.isEmpty(testBatchDAOList)) {return;}//批處理方式 SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);//獲得對應(yīng)的MapperUserTestBatchDOMapper userTestBatchDOMapper = sqlSession.getMapper(UserTestBatchDOMapper.class);try {for (UserTestBatchDO testBatchDO : testBatchDAOList) {userTestBatchDOMapper.insert(testBatchDO);}//統(tǒng)一提交sqlSession.commit();} catch (Exception e) {//沒有提交的數(shù)據(jù)可以回滾sqlSession.rollback();} finally {//關(guān)閉 sqlSessionsqlSession.close();} }

測試結(jié)果

數(shù)量耗時
10002174ms
20003104ms
30003801ms
40004991ms
50005930ms
80008151ms
100008252ms

批量修改

1.方式一

批量新增或更新方式
注:需要給唯一主鍵添加唯一索引,update才會生效

<!-- 批量新增或更新--> <insert id="batchSaveOrUpdate" parameterType="java.util.List">INSERT INTO lp_user_test_batch(id,user_id,user_name,user_age,type,create_time,update_time)VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.id,jdbcType=BIGINT},#{item.userId,jdbcType=VARCHAR},#{item.userName,jdbcType=VARCHAR},#{item.userAge,jdbcType=INTEGER},#{item.type,jdbcType=INTEGER},#{item.createTime,jdbcType=TIMESTAMP},#{item.updateTime,jdbcType=TIMESTAMP})</foreach>ON DUPLICATE KEY UPDATEuser_name = VALUES(user_name),user_age = VALUES(user_age),type = VALUES(type),update_time = VALUES(update_time) </insert>

測試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時
10001505ms
20002617ms
30002922ms
40003292ms
50003443ms
80004832ms
100004886ms

優(yōu)點:速度快
缺點:使用特殊語法 on duplicate key update 語法 增加sql難度性

2.方式二

單條sql+批量方式的SqlSession

<update id="updateByUserId" >UPDATE lp_user_test_batchSETuser_name = #{userName,jdbcType=VARCHAR},user_age = #{userAge,jdbcType=INTEGER},type = #{type,jdbcType=INTEGER},update_time = #{updateTime,jdbcType=TIMESTAMP}WHERE user_id = #{userId,jdbcType=VARCHAR} </update> @Resource(name = "sqlSessionFactory") private SqlSessionFactory sqlSessionFactory;/*** 利用 MyBatis 批處理特性,批量更新*/ public void batchUpdate(List<UserTestBatchDO> testBatchDAOList) {//集合非空if (CollectionUtils.isEmpty(testBatchDAOList)) {return;}//批處理方式 SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);//獲得對應(yīng)的MapperUserTestBatchDOMapper userTestBatchDOMapper = sqlSession.getMapper(UserTestBatchDOMapper.class);try {for (UserTestBatchDO testBatchDO : testBatchDAOList) {userTestBatchDOMapper.updateByUserId(testBatchDO);}//統(tǒng)一提交sqlSession.commit();//清理緩存,防止溢出sqlSession.clearCache();} catch (Exception e) {//沒有提交的數(shù)據(jù)可以回滾sqlSession.rollback();} finally {//關(guān)閉 sqlSessionsqlSession.close();} }

測試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時
10003158ms
20004324ms
30006466ms
40007572ms
50009812ms
800012846ms
1000016088ms

優(yōu)點:通過日志觀察,生成一條執(zhí)行語句sql ,多行參數(shù),統(tǒng)一commit
缺點:比方式一速度略慢

3.方式三

java程序循環(huán)調(diào)用單條修改語句
執(zhí)行方式:一條sql ,程序循環(huán)執(zhí)行

for (UserTestBatchDO userTestBatch : testBatchDAOList) {userTestBatchDOMapper.updateByUserId(userTestBatch); }

測試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時
100033907ms
200042866ms
300089675ms
5000?104833ms

優(yōu)點:方便單條控制提交事物
缺點:耗時,耗性能、每一次循環(huán)都需要與數(shù)據(jù)庫交互一次

4.方式四

Mybatis foreach 循環(huán)
執(zhí)行方式:拼接好一條sql,后執(zhí)行

<!-- 接收list參數(shù),循環(huán)著組裝sql語句,注意for循環(huán)的寫法separator=";" 代表著每次循環(huán)完,在sql后面放一個分號 --> <update id="updateForeachByUserId" parameterType="java.util.List"><foreach collection="list" item="item" separator=";">UPDATE lp_user_test_batchSETuser_name = #{item.userName,jdbcType=VARCHAR},user_age = #{item.userAge,jdbcType=INTEGER},type = #{item.type,jdbcType=INTEGER},update_time = #{item.updateTime,jdbcType=TIMESTAMP}WHERE user_id = #{item.userId,jdbcType=VARCHAR}</foreach> </update>

測試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時
10002671ms
2000?4170ms
30004514ms
40005152ms
5000?6572ms
800010209ms
1000012158ms

優(yōu)點:生成多條sql,統(tǒng)一執(zhí)行,與數(shù)據(jù)庫交互次數(shù)少
缺點 : 生成多條拼接的update語句,update語句比較多,量大了就有可能造成sql阻塞。

5.方式五

mybatis sql 使用 case when

<!-- 批量更新第二種方法,通過 case when語句變相的進行批量更新 --><update id="updateCaseByUserId" parameterType="java.util.List">update lp_user_test_batch<trim prefix="set" suffixOverrides=","><!-- 拼接case when 這是另一種寫法 --><trim prefix="user_name =case" suffix="end,"><foreach collection="list" item="item"><if test="item.userName!=null">when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.userName,jdbcType=VARCHAR}</if></foreach></trim><trim prefix="user_age =case" suffix="end,"><foreach collection="list" item="item"><if test="item.userAge!=null">when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.userAge,jdbcType=INTEGER}</if></foreach></trim><trim prefix="type =case" suffix="end,"><foreach collection="list" item="item"><if test="item.type!=null">when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.type,jdbcType=INTEGER}</if></foreach></trim><trim prefix="update_time =case" suffix="end,"><foreach collection="list" item="item"><if test="item.type!=null">when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.updateTime,jdbcType=TIMESTAMP}</if></foreach></trim></trim><where>user_id in<foreach collection="list" index="index" item="item" separator="," open="(" close=")">#{item.userId,jdbcType=VARCHAR}</foreach></where></update>

測試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時
10003201ms
20004804ms
30006833ms
40008554ms
500011688ms
800026501ms
1000034724ms

缺點:
xml中的循環(huán)體有點多,每一個case when 都要循環(huán)一遍list集合,所以大批量拼sql的時候會比較慢。
生成多條拼接sql,sql長度過長,容易sql超長引起報錯 Packet for query is too large。

MySQL 最大允許的 packet

Mybatis批處理介紹

Mybatis內(nèi)置執(zhí)行器類型ExecutorType有3種
分別是
ExecutorType.SIMPLE: 不做特殊處理,為每個語句的執(zhí)行創(chuàng)建一個新的預(yù)處理語句。
ExecutorType.REUSE: 可以復(fù)用預(yù)處理語句。
ExecutorType.BATCH:可以批量執(zhí)行所有更新語句

SIMPLE與BATCH(批量)對比
默認的是simple,該模式下它為每個語句的執(zhí)行創(chuàng)建一個新的預(yù)處理語句,單條提交sql;
而batch模式重復(fù)使用已經(jīng)預(yù)處理的語句,并且批量執(zhí)行所有更新語句,顯然batch性能將更優(yōu);但是批量模式無法返回自增主鍵

測試環(huán)境配置

系統(tǒng):win 8.1
Mysql : 5.7
java環(huán)境:junit
注:環(huán)境不同可能會引起耗時存在差異。

總結(jié)

單次批量操作不要過大,批量新增使用方式一,批量更新方式一與方式二經(jīng)過測試是最優(yōu)的選擇
也可以根據(jù)安全方面綜合考慮,選擇適合的方式。

關(guān)注程序員小強公眾號更多編程趣事,知識心得與您分享

總結(jié)

以上是生活随笔為你收集整理的Mybatis 批量操作8种实现总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。