on duplicate key update 批量更新操作

2021-08-13  本文已影响0人  thinking2019
适用约束:

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

最近发现一个问题:

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

表结果

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);
    }
上一篇下一篇

猜你喜欢

热点阅读