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>

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

(0)

相关推荐

  • 解决mybatis批量更新(update foreach)失败的问题

    如下所示: <!--批量更新报表 --> <update id="updateIssueByBatch" parameterType="java.util.List"> <foreach collection="issueList" item="item" index="index" separator=";"> update sys_issue &l

  • mybatis使用foreach语句实现IN查询(三种)

    foreach语句中, collection属性的参数类型可以使:List.数组.map集合 collection: 必须跟mapper.java中@Param标签指定的元素名一样 item : 表示在迭代过程中每一个元素的别名,可以随便起名,但是必须跟元素中的#{}里面的名称一样. index :表示在迭代过程中每次迭代到的位置(下标) open :前缀, sql语句中集合都必须用小括号()括起来 close :后缀 separator :分隔符,表示迭代时每个元素之间以什么分隔 Mybati

  • mybatis-plus  mapper中foreach循环操作代码详解(新增或修改)

    .循环添加 接口处: 分别是 void 无返回类型 :有的话是(resultType)返回类型,参数类型(parameterType) list , 如: 在mapper文件中分别对应ID,参数类型和返回类型. 循环处理,如下: <insert id="insertPack" parameterType="java.util.List"> insert into t_ev_bu_pack ( PACK_CODE, BIN, PACK_PROD_TIME,

  • mybatis3.4.6 批量更新 foreach 遍历map 的正确姿势详解

    好久没编码了!最近开始编码遇到一个问题 !一个批量修改的问题,就是mybatis foreach 的使用. 当时使用的场景 ,前端 传逗号拼接的字符串id, 修改id对应数据的数据顺序 ,顺序 就是id 的顺序. 就是一个条件(单个id值) 修改一个值(传入的id的顺序) , 1. 把条件作为Map 的key 修改值是value,用map入参 2.用List<Object> 或者数组 ,把条件和值封装成对象放进list集合或者array数组 3.代码使用for循环调用mapper方法 穿两个参

  • 解决mybatis使用foreach批量insert异常的问题

    异常 org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version fo

  • Mybatis动态SQL foreach标签用法实例

    需求:传入多个 id 查询用户信息,用下边两个 sql 实现: SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16) SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16) 这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来. 这样我们将如何进行参数的传递? 1.实体类 public class Qu

  • MyBatis foreach 批量更新实例

    在做配置选项(设备类型,所属楼层等)的时候,当删除某配置的时候,我需要检验该配置是否已被删除. @Override public BaseVO deleteOptionDetail(Integer id) { // 合法性验证 if (null == id) { return ParamErrorVO.getInstance(); } ConfigOptionDetail configOptionDetail = configOptionDetailMapper.selectById(id);

  • mybatis执行批量更新batch update 的方法(oracle,mysql两种)

    Oracle和MySQL数据库的批量update在mybatis中配置不太一样: oracle数据库: <code class="hljs tcl" style=""><<span class="hljs-keyword" style="">update</span> id=<span class="hljs-string" style=""

  • mybatis foreach批量插入数据:Oracle与MySQL区别介绍

    下面给大家介绍mybatis foreach批量插入数据:Oracle与MySQL不同点: •主要不同点在于foreach标签内separator属性的设置问题: •separator设置为","分割时,最终拼接的代码形式为:insert into table_name (a,b,c) values (v1,v2,v3) ,(v4,v5,v6) ,... •separator设置为"union all"分割时,最终拼接的代码形式为:insert into table

  • 详解扩展tk.mybatis的批量更新的功能

    tk.mybatis没有带批量更新的功能,批量更新却是经常使用的,所以需要自己实现. 批量更新网上主要有2种方式:case when方式.foreach方式 但是foreachzhe这种方式效率非常低下,不知道为何那多么帖子在流传,请看我另一个文章. 扩展tk.mybatis的批量更新,采用case when方式,源码干货如下: 首先定义下mapper接口 import org.apache.ibatis.annotations.UpdateProvider; import java.util.

  • Oracle + Mybatis实现批量插入、更新和删除示例代码

    前言 Mybatis是web工程开发中非常常用的数据持久化的框架,通过该框架,我们非常容易的进行数据库的增删改查.数据库连接进行事务提交的时候,需要耗费的资源比较多,如果需要插入更新的数据比较多,而且每次事务只提交一条数据,会造成非常大的数据库资源浪费,导致数据库性能.系统性能大幅度下降. 关于mybatis的批量插入,网上的多数示例多半是关于MySQL数据库的,关于Oracle数据库的例子比较少.本文将给大家介绍关于Oracle+Mybatis批量插入.更新和删除的相关内容,下面话不多说了,来

  • Mybatis批量更新报错问题

    下面给大家介绍mybatis批量更新报错问题, allowMultiQueries=true 后来发现是jdbc链接没有加允许批量更新操作的参数引起的,不加会报badsql,mysql版的mybatis批量更新操作如下 <update id="updateOrderOverdueStatus" parameterType="java.util.List"> <foreach collection="list" item=&quo

  • Mybatis批量更新三种方式的实现

    Mybatis实现批量更新操作 方式一: <update id="updateBatch" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" open="" close="" separator=";">

  • Fluent Mybatis 批量更新的使用

    目录 批量更新同一张表的数据 更新多条数据,每条数据都不一样 java中for循环实现方式 一条SQL,服务端逐条更新 mybatis实现方式 使用FluentMybatis实现方式 使用mysql的Case When then方式更新 mybatis原生实现方式 批量更新不同的表数据 参考 批量更新同一张表的数据 更新多条数据,每条数据都不一样 背景描述 通常需要一次更新多条数据有两个方式 在业务代码中循环遍历,逐条更新 一次性更新所有数据, 采用批量sql方式,一次执行. 更准确的说是一条s

  • mybatis实现批量修改-xml方式

    目录 mybatis批量修改-xml mybatis xml批量更新值 mybatis批量修改-xml mybatis批量查询,批量新增就不聊了,今天看看批量修改. 直接上代码吧 xml文件中代码如下: <update id="batchUpdate" parameterType="java.util.List"> update pat_doc_pat_info set sex= <foreach collection="list&quo

  • mybatis如何批量修改数据

    目录 批量修改主要有两种方式 第一种 第二种 mysql及mybatis批量更新数据update mysql批量更新update mybatis实现批量更新update 批量修改主要有两种方式 第一种 可以通过for循环一条一条修改数据,这样会影响效率,因此我不推荐,所以在这里我也不多说. 第二种 通过修改mybatis中mapper.xml文件,如下: <update id="updateRoleMenus" parameterType="java.util.List

随机推荐