有一小段时间没有写技术博文了,今天我又来更新啦5月份中间有个小插曲,那就是我在单位打球意外导致脚跟腱受伤,然后住院在家修养了一个多月了,所以小伙伴们在外锻炼时还是时刻注意自身的安全哦!6月份这一个月都是居家办公的状态,庆幸自己是计算机专业的,不然可惨了!
记录最近工作中遇到的问题以及解决的办法,也就是今天的主题:Mybatis批量插入数据。
数据的单条插入,小伙伴应该对此并不陌生了,因为在之前的博文中已经介绍过如何进行基础的增加数据过程,这里不再累赘,如果这部分内容忘记的小伙伴可以参考此条链接:SpringBoot_实现基本增删改查(前后端分离版),中间本人已经描述清楚了!
不过,随着项目越做越多,深度也越来越来大,基本的插入数据量还是偏小,如果我们项目需要我们一次性插入成百上千的数据呢?单条数据是不够看啦,问题引入进来,如何插入批量数据呢?
单条插入的速度我们如果用飞机的速度描述,那么批量插入的速度就是火箭。为何这样子说呢?因为本人亲身经历过,在这之前没有仔细了解过批量插入,单条的速度就能满足我当前接手项目中的需求,一般的业务批量插入的情况少嘛!但是6月份需要做的事情中当前数据暂无,大量的数据只能通过我在代码层面进行模拟生成,涉及到每年每月每天每小时的数据,数据量可想而知,一条条插入到数据库中来,即便是我们加上了时间索引,速度还是想蜗牛爬似的。
话不多说,直接上批量插入的用法:
批量的意思就是多条数据一并插入于数据库之中,那么我们传入到数据库肯定就是以集合传值。批量插入数据时不能像单条数据一样插入一个对象了,如下例所示为单条模拟增加和多条模拟增加数据的区分:
/** 单条模拟增加数据 */
public int insertSimulationData(TunnelDetectData tunnelDetectData);
/** 多条模拟增加数据 */
public int insertSimulationDataList(List<TunnelDetectData> tunnelDetectDataList);
以下将通过单条数据插入和批量插入做对比分析,代码实例如下:
(1)单条数据插入:
单条的数据插入注意因为id是自增的,所以加入
等让主键id自增,数据库层面也要将主键id设置为自动新增,否则程序会报错!
<insert id="insertSimulationData" parameterType="com.yh.domain.TunnelDetectData" keyProperty="id" useGeneratedKeys="true">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID() as id
</selectKey>
insert into tunnel_detect_data
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="stakeNo != null" >
stake_no,
</if>
<if test="deviceNo != null" >
device_no,
</if>
<if test="deviceName != null" >
device_name,
</if>
<if test="tunnelName != null" >
tunnel_name,
</if>
<if test="direction != null" >
direction,
</if>
<if test="commandType != null" >
command_type,
</if>
<if test="currentData != null" >
current_data,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="acquisitionTime != null" >
acquisition_time,
</if>
<if test="loadTime != null" >
load_time,
</if>
<if test="remark1 != null" >
remark1,
</if>
<if test="remark2 != null" >
remark2,
</if>
<if test="remark3 != null" >
remark3,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=BIGINT},
</if>
<if test="stakeNo != null" >
#{stakeNo,jdbcType=VARCHAR},
</if>
<if test="deviceNo != null" >
#{deviceNo,jdbcType=VARCHAR},
</if>
<if test="deviceName != null" >
#{deviceName,jdbcType=VARCHAR},
</if>
<if test="tunnelName != null" >
#{tunnelName,jdbcType=VARCHAR},
</if>
<if test="direction != null" >
#{direction,jdbcType=INTEGER},
</if>
<if test="commandType != null" >
#{commandType,jdbcType=VARCHAR},
</if>
<if test="currentData != null" >
#{currentData,jdbcType=VARCHAR},
</if>
<if test="createTime != null" >
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="acquisitionTime != null" >
#{acquisitionTime,jdbcType=TIMESTAMP},
</if>
<if test="loadTime != null" >
#{loadTime,jdbcType=TIMESTAMP},
</if>
<if test="remark1 != null" >
#{remark1,jdbcType=VARCHAR},
</if>
<if test="remark2 != null" >
#{remark2,jdbcType=VARCHAR},
</if>
<if test="remark3 != null" >
#{remark3,jdbcType=VARCHAR},
</if>
</trim>
</insert>
(2)多条数据批量插入:
多条数据批量插入的写法有所不同,以集合的形式插入,需要借助
,代码实例如下所示:
注意
键值对中各个参数的写法:
collection:为必填值,值为要迭代循环的集合类型,情况有多种:
入参是List类型的时候,collection属性值为list,这里是否可换其他自定义值,我还未亲测过,好像有大佬们换过吧?
入参是Map类型的时候,collection 属性值为map的key值。
item:每一个元素进行迭代时的别名,可自行定义,省事就直接用“item”即可。
index:索引的属性名,在集合数组情况下值为当前索引值,当迭代对象是map时,这个值是map的key。
separator: 每次循环的分隔符。
<insert id="insertSimulationDataList" >
insert into tunnel_detect_data
(stake_no, device_no,
device_name, tunnel_name, direction,
command_type, current_data, create_time,
acquisition_time, load_time, remark1,
remark2, remark3)
values
<foreach collection="list" separator="," index="index" item="item">
(#{item.stakeNo},
#{item.deviceNo},
#{item.deviceName},
#{item.tunnelName},
#{item.direction},
#{item.commandType},
#{item.currentData},
#{item.createTime},
#{item.acquisitionTime},
#{item.loadTime},
#{item.remark1},
#{item.remark2},
#{item.remark3})
</foreach>
</insert>
路过的小伙伴,如果博文有帮助到你解决问题,可以点赞+收藏+关注一波呀~本人将会持续更新相关学习博文,感谢您的支持哦!!!芜湖起飞✈️✈️✈️