MyBatis foreach 批量更新实例

 更新时间:2021年01月25日 09:31:51   作者:Monicase  
这篇文章主要介绍了MyBatis foreach 批量更新实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

在做配置选项(设备类型,所属楼层等)的时候,当删除某配置的时候,我需要检验该配置是否已被删除。

@Override
 public BaseVO deleteOptionDetail(Integer id) {
 
  // 合法性验证
  if (null == id) {
   return ParamErrorVO.getInstance();
  }
  ConfigOptionDetail configOptionDetail = configOptionDetailMapper.selectById(id);
  if (null == configOptionDetail || 1 == configOptionDetail.getIsDeleted()) {
   return new ErrorVO("该配置不存在");
  }
  if (configOptionDetail.getSystem() == 1) {
   return new ErrorVO("系统属性不能删除");
  }
  if (configOptionDetail.getUseCount() = 0) {
   return new ErrorVO("配置正在使用不能删除,请先删除使用配置的地方");
  }
 
  // 合法性通过
  configOptionDetail.setIsDeleted(1);
  configOptionDetail.setGmtModefied(Calendar.getInstance().getTime());
  configOptionDetailMapper.updateById(configOptionDetail);
 
  // 更新内存配置
  ConfigOptionConstruct.updateOption();
  return SuccessVO.getInstance();
 }

思考之后我决定采用,给配置选项设备一个use_count字段,代表该配置被引用的次数。 只有当该字段值为 0 时,该配置选项记录才可被删除。

使用情况:

我需要批量删除房间, 删除房间的同时,room对象中使用到了所属楼层的配置选项,我需要将他们的引用减少

@Override
 public BaseVO deleteRoomByIds(Integer[] ids) {
  if (null == ids) {
   return ParamErrorVO.getInstance();
  }
  EntityWrapper<Room> entityWrapper = new EntityWrapper<>();
  entityWrapper.where("isdelete={0}", 0);
  // 核查删除的房间中是否存在正在使用的设备
  List<Integer> notDelete = deviceInfoService.checkRoomIds(ids);
  if (null != notDelete && 0 != notDelete.size()) {
   // 存在仍在使用设备的房间
   entityWrapper.in("id", notDelete);
   // 查询这些房间
   List<Room> roomList = roomMapper.selectList(entityWrapper);
   // 获取房间的名称
   StringBuilder stringBuilder = new StringBuilder(roomList.stream().map(Room::getName).collect(Collectors.toList()).toString());
   System.out.println(stringBuilder);
   // TODO: 2018/4/8 可能需要修改提示语
   return new ErrorVO(stringBuilder + " 房间存在未删除的设备,请先删除设备");
  }
 
  // 房间没有设备在使用
  List<Integer> idList = new ArrayList<>();
  idList.addAll(Arrays.asList(ids));
  // 查询需要删除的房间
  entityWrapper.in("id", idList);
  List<Room> roomList = roomMapper.selectList(entityWrapper);
  if (null == roomList || idList.size() != roomList.size()) {
   return new ErrorVO("存在错误的房间");
  }
  // ******************************************************************************************** 重点
  // 可以逻辑删除
  int count = roomMapper.logicDeleteByIds(idList);
  List<Long> optionIds = roomList.stream().map(room -> Long.parseLong(room.getRoomPosition())).collect(Collectors.toList());
  Map<Long, Long> optionIdsMap = optionIds.stream().collect(Collectors.groupingBy(p -> p,Collectors.counting()));
  // 移除所属楼层配置选项的使用
  configOptionDetailService.removeUseCount(optionIdsMap);
  ConfigOptionConstruct.updateOption();
  if (count == idList.size()) {
   return SuccessVO.getInstance();
  } else {
   return new ErrorVO("部分删除失败");
  } 
 }

optionIds 是从roomList 房间集合中,通过stream, 所引用的配置选项id集合

上面我红字标明他们,是因为,如果房间A 是一楼, 房间B 也是一楼, 那么我应该将一楼的引用减 2。

所以我将optionIds 分组转成Map<配置选项id, 需要减少引用的次数>

最后一步,也是最重要的进行数据库操作,我希望可以批量更新减少这些引用。

查看MyBatis文档:

foreach

动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
 SELECT *
 FROM POST P
 WHERE ID in
 <foreach item="item" index="index" collection="list"
  open="(" separator="," close=")">
  #{item}
 </foreach>
</select>

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。

注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

<update id="addUseCountByIds">
 update config_option_detail
 set gmt_modified = #{gmtModified}, use_count = use_count +
 <foreach item="item" index="index" collection="list" open=" case id " separator=" " close=" end">
 when #{index} then #{item}
 </foreach>
 where id in
 <foreach item="item" index="index" collection="list"
  open="(" separator="," close=")">
 #{index}
 </foreach>
</update>

补充:mybatis 用<foreach>根据ID批量更新时的一个注意点。

看接口。传入一个Long型的List。

int updateReadCount(@Param(value = "topicIdList") List<Long> topicIdList);

xml里面循环update.

<update id="updateReadCount" parameterType="java.util.List">
  update CTS
  set read_count = read_count + 1
  where topic_id in
  <foreach item="item" index="index" collection="topicIdList" open="(" close=")" separator=",">
   #{item.topicId}
  </foreach>
 </update>

就是直接复制了别人的代码,改了一改。怎么都跑不通。。。。。。。

问题就出在这个item,item 表示集合中每一个元素进行迭代时的别名。

List<Long> topicIdList 因为时Long型(不是entity封装着的),就不需要别名了。改为如下就可以跑通了。

<update id="updateReadCount" parameterType="java.util.List">
  update CTS
  set read_count = read_count + 1
  where topic_id in
  <foreach item="topicId" index="index" collection="topicIdList" open="(" close=")" separator=",">
   #{topicId}
  </foreach>
 </update>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

相关文章

  • Java之Default关键字的两种使用方式

    Java之Default关键字的两种使用方式

    Java关键字default主要有两种使用场景:一是在switch语句中作为默认执行的分支;二是在接口中定义默认方法,这是Java 8新增的特性,允许接口包含具体实现的方法,在switch中,当没有匹配的case时,执行default分支
    2024-09-09
  • 使用RestTemplate调用https接口跳过证书验证

    使用RestTemplate调用https接口跳过证书验证

    这篇文章主要介绍了使用RestTemplate调用https接口跳过证书验证,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Netty分布式NioEventLoop优化selector源码解析

    Netty分布式NioEventLoop优化selector源码解析

    这篇文章主要介绍了Netty分布式NioEventLoop优化selector源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • java 学习笔记(入门篇)_java程序helloWorld

    java 学习笔记(入门篇)_java程序helloWorld

    安装配置完Java的jdk,下面就开始写第一个java程序--hello World.用来在控制台输出“Hello World”,接下来详细介绍,感兴趣的朋友可以参考下
    2013-01-01
  • SpringBoot中配置Web静态资源路径的方法

    SpringBoot中配置Web静态资源路径的方法

    这篇文章主要介绍了SpringBoot中配置Web静态资源路径的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • SpringBoot接口接收json参数解析

    SpringBoot接口接收json参数解析

    这篇文章主要介绍了SpringBoot接口接收json参数解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java 高并发编程之最实用的任务执行架构设计建议收藏

    Java 高并发编程之最实用的任务执行架构设计建议收藏

    高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求,高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等
    2021-10-10
  • 使用Spring Data Jpa的CriteriaQuery一个陷阱

    使用Spring Data Jpa的CriteriaQuery一个陷阱

    使用Spring Data Jpa的CriteriaQuery进行动态条件查询时,可能会遇到一个陷阱,当条件为空时,查询不到任何结果,并不是期望的返回所有结果。这是为什么呢?
    2020-11-11
  • Sping Security前后端分离两种实战方案

    Sping Security前后端分离两种实战方案

    这篇文章主要介绍了Sping Security前后端分离两种方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Java变量的初始化及静态方法的实现

    Java变量的初始化及静态方法的实现

    这篇文章主要介绍了Java变量的初始化及静态方法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10

最新评论