美文网首页
on duplicate key update 批量更新操作

on duplicate key update 批量更新操作

作者: thinking2019 | 来源:发表于2021-08-13 18:12 被阅读0次
    适用约束:

    虽然更新很快,但是也有约束, 必须保证更新的字段要统一,如果不同意就会漏更新,或者报错.

    最近发现一个问题:

    执行这个更新方法后,马上查询, 查询到的是更新前的数据.

    表结果

    CREATE TABLE `t_a` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `a1` varchar(255) DEFAULT NULL,
      `a2` varchar(255) DEFAULT NULL,
      `a3` varchar(255) DEFAULT NULL,
      `c` datetime DEFAULT CURRENT_TIMESTAMP,
      `u` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    

    批量更新

    INSERT INTO t_a (
        id,a1,a2,a3
    )
    VALUES
    ( 1,'11','121','131' ),
    ( 2,'21','22','23' )
    ON DUPLICATE KEY UPDATE 
    a1 = VALUES(a1),
    a2 = VALUES(a2)
    

    讲解

    ##第一部分:需要注意的是 =>一定要带唯一主键的字段,没带就只会新增不会修改
    INSERT INTO t_a (
        id,a1,a2,a3
    )
    VALUES
    ( 1,'11','121','131' ),
    ( 2,'21','22','23' )
    
    ##第二部分:这列出来的是需要修改的字段,不想被修改就不要在这里加,不管a3值是否变化,值都不会被修改
    a1 = VALUES(a1),
    a2 = VALUES(a2)
    

    mybatis中的使用

     <insert id="batchUpdate" parameterType="java.util.List">
            insert into t_a
            (id,a1,a2,a3)
            values
            <foreach collection="list" item="item" index="index" separator=",">
                (#{item.id},
                #{item.a1},
                #{item.a2},
                #{item.a3})
            </foreach>
            ON DUPLICATE KEY UPDATE
            a1 = VALUES(a1),
            a2 = VALUES(a2)
        </insert>
    

    无法做到动态判断是否有值,且需要修改,方法调整 --- 笨办法

    <insert id="batchUpdate">
      INSERT INTO t_a (   
         ${columnList}  
       ) VALUES  
      <foreach item='item' index='index' collection='list' separator=','>  
         ( ${insertColumnList} ) 
      </foreach> 
       ON DUPLICATE KEY UPDATE ${updateColumnList}
    </insert>
    

    备注:
    columnList:需要更新的字段(检查对象中不为null的字段集合,例如:id,a1,a2,a3)
    insertColumnList:在对象中取值的字符串,更columnList对应,例如:#{item.id},#{item.a1},#{item.a2},#{item.a3}
    updateColumnList:修改更新的字段集合,例如:a1 = VALUES(a1),a2 = VALUES(a2)

    疑惑

    这个sql执行返回值并不是被修改的条数,有点费解

    配套适用的 getColumnListByNotNull

    拙劣的封装,不喜勿喷...

    /**
         * on duplicate key update  修改需要的对象
         * @param list 处理集合
         * @param <T> 处理对象
         * @return 获取有效字段
         */
        public static <T> List<String> getColumnListByNotNull(List<T> list) {
            // 不处理
            if(CollectionUtils.isEmpty(list)){
                log.error("getColumnListByNotNull处理集合为空");
                return Lists.newArrayList();
            }
            // 取其中一条记录来确认需要修改字段
            T t = list.get(0);
            // 获取全部属性
            List<Field> allFieldsList = FieldUtils.getAllFieldsList(t.getClass());
            // 排除非静态属性 + 非空值对象
            List<String> columnListByNotNull = allFieldsList.stream().filter(f -> {
                try {
                    f.setAccessible(true);
                    // 排除静态属性
                    if (Modifier.isStatic(f.getModifiers())) {
                        return false;
                    }
                    return null != f.get(t);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    log.error("getColumnListByNotNull异常2", e);
                    return false;
                }
            }).map(Field::getName).collect(Collectors.toList());
            // 异常情况
            if (CollectionUtils.isEmpty(columnListByNotNull)) {
                log.error("对象中包含非null属性个数为0,getColumnListByNotNull = {}", JSON.toJSONString(t));
                throw new PlatformException("对象中包含非null属性个数为0");
            }
            if (!columnListByNotNull.contains("id")) {
                log.error("对象中id的值为null,getColumnListByNotNull = {}", JSON.toJSONString(t));
                throw new PlatformException("对象中id的值为null");
            }
            // 组装
            String columnList = String.join(",", columnListByNotNull);
            log.info("on duplicate key update => columnList={}", columnList);
            String updateColumnList = columnListByNotNull.stream().map(n -> n.concat("=").concat("values(").concat(n).concat(")")).collect(Collectors.joining(","));
            log.info("on duplicate key update => updateColumnList={}", updateColumnList);
            String insertColumnList = columnListByNotNull.stream().map(n -> "#{item.".concat(n).concat("}")).collect(Collectors.joining(","));
            log.info("on duplicate key update => updateColumnList={}", insertColumnList);
    
            return Lists.newArrayList(columnList, updateColumnList, insertColumnList);
        }
    

    相关文章

      网友评论

          本文标题:on duplicate key update 批量更新操作

          本文链接:https://www.haomeiwen.com/subject/evljbltx.html