重新 mybatis plus 的 撒着OrUpdate 方法,实现根据自定义字段插入或者修改

发布于:2025-08-09 ⋅ 阅读:(20) ⋅ 点赞:(0)

我希望数据能根据name和content作为唯一索引,如果 数据库中的数据, name和content相同,就更新记录,如果不同,就插入记录。

废话不多说,直接上代码。


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdateBatch(Collection<FulfillmentItem> entityList) {
        return SqlHelper.saveOrUpdateBatch(
            this.getEntityClass(),
            this.currentMapperClass(),
            super.log,
            entityList,
            DEFAULT_BATCH_SIZE,
            (sqlSession, entity) -> {
                Wrapper<FulfillmentItem> queryWrapper = Wrappers.<FulfillmentItem>lambdaQuery()
                    .eq(FulfillmentItem::getName, entity.getName())
                    .eq(FulfillmentItem::getContent, entity.getContent());
                Map<String, Object> map = new HashMap<>();
                map.put(Constants.WRAPPER, queryWrapper);
                return CollectionUtils.isEmpty(sqlSession.selectList(this.getSqlStatement(SqlMethod.SELECT_LIST), map));
            },
            (sqlSession, entity) -> {
                Wrapper<FulfillmentItem> lambdaUpdateWrapper = Wrappers.lambdaUpdate(FulfillmentItem.class)
                    .eq(FulfillmentItem::getName, entity.getName())
                    .eq(FulfillmentItem::getContent, entity.getContent());
                Map<String, Object> map = new HashMap<>();
                map.put(Constants.ENTITY, entity);
                map.put(Constants.WRAPPER, lambdaUpdateWrapper);
                sqlSession.update(getSqlStatement(SqlMethod.UPDATE), map);
            });
    }

注意点:
saveOrUpdateBatch 本质是先查后改,高并发业务请谨慎取用。

mybatis 旧版本略有不同,没有 this.getEntityClass() 方法。
原因是旧版本中,entityClass 属性是 protectd 类型,可以直接用,
springboot 3 后的版本,改成了 private 类型。

源码:

    private Class<T> entityClass; // 旧版本是 protected类型

    public Class<T> getEntityClass() {
        if (this.entityClass == null) {
            this.entityClass = GenericTypeUtils.resolveTypeArguments(this.getMapperClass(), BaseMapper.class)[0];
        }

当然,这里也可以根据 name 和 content 作为唯一索引,用 MySQL 的 ON DUPLICATE KEY UPDATE 来做判断。

但是由于我content是text类型,无法用作索引列。

如果高并发下,非要用 DUPLICATE KEY UPDATE,可以加一列:content_hash.
通过存储 content 内容的哈希值,来做唯一索引,也能解决这个问题。


网站公告

今日签到

点亮在社区的每一天
去签到