MyBatis批量操作(批量插入、批量删除、批量更新)

1 篇文章 0 订阅
1 篇文章 0 订阅

今天有了新的需求,需求内容是要读取表内的1000条数据,然后批量增加到另一张表,并且把查到的这1000条数据批量删除,说到这里,我就想到了forEach标签,因为自己的记性不太好,因此写一篇博客,记录一下,以后可以直接用。forEach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。

forEach元素的属性主要有 item,index,collection,open,separator,close。

item表示集合中每一个元素进行迭代时的别名,循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。 具体说明:在list和数组中是其中的对象,在map中是value,该参数为必选。

index指定一个名字,用于表示在迭代过程中,每次迭代到的位置。在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。

open表示该语句以什么开始。foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。

separator表示在每次进行迭代之间以什么符号作为分隔符。元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。

close表示以什么结束。foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。

在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:
1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key。下面就以我自己写的需求为例,话不多说,上代码:

首先是Mapper接口类, insertBatch和deleteBatchByFileId这两个方法是批量操作方法,这里要注意,一定要有@Param注解,来给集合起一个名字

    /**
     * 功能描述 //TODO 查询t_res_send_file表中状态为2的1000条数据
     * @author 王弈程
     * @date 2021/12/20 11:18
     * @return: java.util.List<com.unicom.resinteractive.api.service.ResSendFileService>
     */
    List<ResSendFile> findStatusIs2();

    /**
     * 功能描述 //TODO 把从t_res_send_file表中查询到状态为2的1000条数据批量插入到t_res_send_file_history表中
     * @author 王弈程
     * @date 2021/12/20 11:36
     * @param resSendFileHistory:
     * @return: void
     */
    void insertBatch(@Param("list") List<ResSendFileHistory> resSendFileHistory);

    /**
     * 功能描述 //TODO 把从t_res_send_file表中读取读取到的resSendFileId放到List中,并且执行批量删除
     * @author 王弈程
     * @date 2021/12/20 14:06
     * @param resSendFileId:  文件领取数据表ID
     * @return: int
     */
    int deleteBatchByFileId(@Param("list") List<Long> resSendFileId);

接下来是Mapper映射文件,这里我也说明一下,parameterType这里是List或者实体类都可以,但是forEach里面的collection=“list”,这个list必须是Mapper接口类里面每个SQL语句对应的方法里面的形参列表@Param(“list”)对应起来

<select id="findStatusIs2" resultMap="BaseResultMap2">
    select
    <include refid="Base_Column_List" />
    from t_res_send_file
    where status = 2
    limit 1000
  </select>

  <insert id="insertBatch" parameterType="com.unicom.resinteractive.po.ResSendFileHistory">
    insert into t_res_send_file_history
    (res_send_file_id, resorder_no, system_id,
      jackpot_code, open_id, send_time,
      status, fail_desc, province_code,
      eparchy_code, create_time, update_time,
      note)
    values
    <foreach collection="list" item="item" index="index" separator=",">
      (#{item.resSendFileId,jdbcType=BIGINT}, #{item.resorderNo,jdbcType=VARCHAR},
       #{item.systemId,jdbcType=VARCHAR}, #{item.jackpotCode,jdbcType=VARCHAR},
       #{item.openId,jdbcType=VARCHAR}, #{item.sendTime,jdbcType=TIMESTAMP},
       #{item.status,jdbcType=INTEGER}, #{item.failDesc,jdbcType=VARCHAR},
       #{item.provinceCode,jdbcType=VARCHAR}, #{item.eparchyCode,jdbcType=VARCHAR},
       #{item.createTime,jdbcType=TIMESTAMP}, #{item.updateTime,jdbcType=TIMESTAMP},
       #{item.note,jdbcType=VARCHAR})
    </foreach>
  </insert>

  <delete id="deleteBatchByFileId">
    delete
    from t_res_send_file
    where res_send_file_id in
    <foreach collection="list" item="item" index="index" open="(" separator="," close=")">
      #{item}
    </foreach>
  </delete>

接下来就是业务逻辑,非常简单的逻辑 

    /**
     * 功能描述 //TODO 从t_res_send_file查询出状态为2的1000条数据批量存到t_res_send_file_history表中,并从t_res_send_file表中删除
     * @author 王弈程
     * @date 2021/12/20 14:18
     * @return: void
     */
    @Override
    public void insertSendFileHistory() {
        while(true){
            //首先查询t_res_send_file表中状态度为2的数据
            List<ResSendFile> statusIs2 = resSendFileHistoryMapper.findStatusIs2();
            if (statusIs2 == null){
                return;
            } else {
                //存从statusIs2遍历出来的对象
                List<ResSendFileHistory> resSendFileHistoryList = new ArrayList<>();
                //存从statusIs2遍历出来的文件ID
                List<Long> resSendFileId = new ArrayList<>();
                //遍历statusIs2,并且把得到的值赋值给resSendFileHistory,赋值完成后,add到resSendFileHistoryList
                for (ResSendFile resSendFile : statusIs2) {
                    ResSendFileHistory resSendFileHistory = new ResSendFileHistory();
                    resSendFileHistory.setResSendFileId(resSendFile.getResSendFileId());
                    resSendFileHistory.setResorderNo(resSendFile.getResorderNo());
                    resSendFileHistory.setSystemId(resSendFile.getSystemId());
                    resSendFileHistory.setJackpotCode(resSendFile.getJackpotCode());
                    resSendFileHistory.setOpenId(resSendFile.getOpenId());
                    resSendFileHistory.setSendTime(resSendFile.getSendTime());
                    resSendFileHistory.setStatus(resSendFile.getStatus());
                    resSendFileHistory.setFailDesc(resSendFile.getFailDesc());
                    resSendFileHistory.setProvinceCode(resSendFile.getProvinceCode());
                    resSendFileHistory.setEparchyCode(resSendFile.getEparchyCode());
                    resSendFileHistory.setCreateTime(resSendFile.getCreateTime());
                    resSendFileHistory.setUpdateTime(resSendFile.getUpdateTime());
                    resSendFileHistory.setNote(resSendFile.getNote());
                    resSendFileHistoryList.add(resSendFileHistory);
                    resSendFileId.add(resSendFile.getResSendFileId());
                }
                //批量增加到t_res_send_file_history表中,不考虑其中的某一条数据是否失败
                resSendFileHistoryMapper.insertBatch(resSendFileHistoryList);
                //批量删除
                resSendFileHistoryMapper.deleteBatchByFileId(resSendFileId);
                if (statusIs2.size() < 1000){
                    return ;
                }
            }
        }
    }

 这里再加入一个批量更新的操作,我感觉实际开发中用处不大

//List类型
<update id="batchUpdateStudent" parameterType="List">  
    UPDATE STUDENT SET name = "5566" WHERE id IN  
    <foreach collection="list" item="item" index="index" open="(" separator="," close=")" >  
        #{item}  
    </foreach>  
</update>


//Map类型

如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key

<update id="batchUpdateStudentWithMap" parameterType="Map" >  
    UPDATE STUDENT SET name = #{name} WHERE id IN   
    <foreach collection="idList" index="index" item="item" open="(" separator="," close=")">   
        #{item}   
    </foreach>  
</update>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值