批量插入或更新数据(MyBatis-plus框架)

这篇具有很好参考价值的文章主要介绍了批量插入或更新数据(MyBatis-plus框架)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.场景说明

2.DUPLICATE 和REPLACE比较

3.批量插入或者更新(两种方式)

方式一:mybatis-plus的saveOrUpdateBatch方法

问题:如果操作类集成了基础类,比如封装了BaseEntity去集成,那么这样使用会出问题

方式二:on duplicate key (推荐)

4.注意

5.常见问题 


1.场景说明

插入数据时,我们经常会遇到这样的情况:

1、首先判断数据是否存在;

2、如果不存在,则插入;

3、如果存在,则更新

需求:根据表中的部分字段去判断插入或者更新

有一张表 hh_adx_monitor_summary

批量插入或更新数据(MyBatis-plus框架)

 ddl:

CREATE TABLE `hh_adx_monitor_summary` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `code` varchar(6) DEFAULT NULL COMMENT '链路编码',
  `plan_id` varchar(32) DEFAULT NULL COMMENT '计划id',
  `cons` int(11) DEFAULT NULL COMMENT '消耗',
  `exp` int(11) DEFAULT NULL COMMENT '曝光数',
  `conv` int(11) DEFAULT NULL COMMENT '转化数',
  `click` int(11) DEFAULT NULL COMMENT '点击数',
  `dimension_time` varchar(32) DEFAULT NULL COMMENT '维度时间',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_hh_adx_monitor_summary_cpd` (`code`,`plan_id`,`dimension_time`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8 COMMENT='监测请求数据汇总';

需要通过code,plan_id,dimension_time判断插入或者更新

INSERT INTO hh_adx_monitor_summary ( CODE, plan_id, cons, exp, conv, click, dimension_time)
VALUES
	( '001001', '1', 6, 3, 0, 0, '20220823' ) 
	ON DUPLICATE KEY UPDATE 
	CODE =VALUES	( CODE ),
	plan_id =VALUES	( plan_id ),
	cons =VALUES	( cons ),
	exp =VALUES	( exp ),
	conv =VALUES	( conv ),
	click =VALUES	( click ),
	dimension_time =VALUES	(	dimension_time)

此时会发现依然会重复插入数据,需要创建一个组合索引

批量插入或更新数据(MyBatis-plus框架)

 添加完索引再次尝试,code,plan_id,dimension_time相同的情况下只会更新不会新增

2.DUPLICATE 和REPLACE比较

replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中, 1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。 2. 否则,直接插入新数据。

3.批量插入或者更新(两种方式)

方式一:mybatis-plus的saveOrUpdateBatch方法

使用saveOrUpdateBatch方法直接调用就可以了,分别在持久层实现Mapper接口,服务层接口继承 IService接口,实现类继承 ServiceImpl接口

1.持久层代码示例

说明:继承BaseMapper即可,泛型使用当前要操作类

package com.hhmt.delivery.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hhmt.delivery.pojo.entity.HhChainCustomerInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;
import java.util.List;

/**
 * 链路客户信息Mapper接口
 *
 * @author huachun
 * @date 2023-01-31
 */
@Mapper
public interface HhChainCustomerInfoMapper extends BaseMapper<HhChainCustomerInfo> {
    

    /**
    * 使用mybatis-plus方式调用saveOrUpdateBatch不需要写这个接口
    boolean saveOrUpdateBatch(@Param("entities") Collection<HhChainCustomerInfo> hhChainCustomerInfos);
    */

}

2.服务层接口示例

说明:继承 IService即可,泛型使用当前要操作类

package com.hhmt.delivery.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.hhmt.delivery.pojo.entity.HhChainCustomerInfo;

import java.util.List;

/**
 * 链路客户信息Service接口
 *
 * @author huachun
 * @date 2023-01-31
 */
public interface IHhChainCustomerInfoService extends IService<HhChainCustomerInfo> {
    
}

3.服务实现类示例

说明:继承ServiceImpl即可,泛型使用持久层操作对象接口类和操作类

package com.hhmt.delivery.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hhmt.delivery.mapper.HhChainCustomerInfoMapper;
import com.hhmt.delivery.pojo.entity.HhChainCustomerInfo;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 链路客户信息Service业务层处理
 *
 * @author huachun
 * @date 2023-01-31
 */
@Service
public class HhChainCustomerInfoServiceImpl extends ServiceImpl<HhChainCustomerInfoMapper, HhChainCustomerInfo> implements IHhChainCustomerInfoService {


    /*@Override
    public boolean saveOrUpdateBatch(Collection<HhChainCustomerInfo> entityList) {
        return hhChainCustomerInfoMapper.saveOrUpdateBatch(entityList);
    }*/

}

4.服务层示例

package com.hhmt.delivery.controller;

import com.hhmt.delivery.core.controller.BaseController;
import com.hhmt.delivery.core.domain.model.ResultVo;
import com.hhmt.delivery.core.page.TableDataInfo;
import com.hhmt.delivery.pojo.entity.HhChainCustomerInfo;
import com.hhmt.delivery.pojo.model.query.HhChainCustomerInfoQuery;
import com.hhmt.delivery.pojo.model.vo.HhChainCustomerInfoVo;
import com.hhmt.delivery.service.IHhChainCustomerInfoService;
import com.hhmt.delivery.valiadtion.Add;
import com.hhmt.delivery.valiadtion.Update;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 链路客户信息Controller
 *
 * @author huachun
 * @date 2023-01-31
 */
@Api(tags = "链路客户信息")
@RestController
@RequestMapping("/chain/HhChainCustomerInfo")
public class HhChainCustomerInfoController extends BaseController {
    @Autowired
    private IHhChainCustomerInfoService hhChainCustomerInfoService;

   
    @ApiOperation("批量插入或更新客户信息")
    @PostMapping("/batch")
    public ResultVo<Integer> addBatch(@Validated(value = Add.class) @RequestBody List<HhChainCustomerInfo> hhChainCustomerInfos) {
        return toAjax(hhChainCustomerInfoService.saveOrUpdateBatch(hhChainCustomerInfos));
    }
    
}

此时调用发现结果是成功的,数据库数据也被更新了(省略过多的测试截图)

批量插入或更新数据(MyBatis-plus框架)

 这种方式在执行时候会通过id判断是否有内容,然后在做更新操作。从打印的sql日志可以看出

批量插入或更新数据(MyBatis-plus框架)

总结:

        1.没有唯一键(id)回自动生成id后新增

        2.有id会查询后判断

        3.查询后数据有差异会调用update语句更新

问题:如果操作类集成了基础类,比如封装了BaseEntity去集成,那么这样使用会出问题

示例如下:

1.BaseEntity类(一般是实体类的公共参数)

package com.hhmt.delivery.core.domain.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.Map;

/**
 * Entity基类
 *
 * @author huachun
 */
@Data
public class BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 搜索值
     */
    private String searchValue;

    /**
     * 创建者
     */
    private String createBy;

    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "创建时间", example = "2022-09-01 13:24:09")
    private Date createTime;

    /**
     * 更新者
     */
    private String updateBy;

    /**
     * 更新时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "创建时间", example = "2022-09-01 13:24:09")
    private Date updateTime;

    /**
     * 备注
     */
    private String remark;

    /**
     * 请求参数
     */
    @JsonIgnore
    private Map<String, Object> params;


}

2.操作类HhChainCustomerInfo继承了BaseEntity

package com.hhmt.delivery.pojo.entity;

import com.hhmt.delivery.annotation.Excel;
import com.hhmt.delivery.constant.VerificationTips;
import com.hhmt.delivery.core.domain.model.BaseEntity;
import com.hhmt.delivery.valiadtion.Update;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.validation.constraints.NotNull;

/**
 * 链路客户信息对象 hh_chain_customer_info
 *
 * @author huachun
 * @date 2023-01-31
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class HhChainCustomerInfo extends BaseEntity {
    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    @NotNull(groups = Update.class, message = VerificationTips.EMPTY_TIPS)
    @ApiModelProperty(value = "${comment}")
    private Long id;

    /**
     * 描述
     */
    @Excel(name = "描述")
    @ApiModelProperty(value = "描述")
    private String description;

    /**
     * 服务
     */
    @Excel(name = "服务")
    @ApiModelProperty(value = "服务")
    private Long serviceId;

    /**
     * 名称
     */
    @Excel(name = "名称")
    @ApiModelProperty(value = "名称")
    private String name;

    /**
     * 编码
     */
    @Excel(name = "编码")
    @ApiModelProperty(value = "编码")
    private String code;

    /**
     * 回传请求方式(1.GET 2.POST)
     */
    @Excel(name = "回传请求方式(1.GET 2.POST)")
    @ApiModelProperty(value = "回传请求方式(1.GET 2.POST)")
    private Integer reqMode;

    /**
     * 上报接口
     */
    @Excel(name = "上报接口")
    @ApiModelProperty(value = "上报接口")
    private String reqApi;

    /**
     * 签名策略
     */
    @Excel(name = "签名策略")
    @ApiModelProperty(value = "签名策略")
    private Integer signPolicy;

}

此时想要进行批量插入或者更新会出现以下问题:

批量插入或更新数据(MyBatis-plus框架)

批量插入或更新数据(MyBatis-plus框架)

有请求id时候被认为是更新,更新会通过id查询判断,问题就出在这里。plus在进行查询时候通过操作类属性去查询,导致了集成的父类属性也进去了,然而在表里面是没有这些字段的,所以出现了上述问题。

方式二:on duplicate key (推荐)

说明:通过sql的方式实现批量的插入或更新,这种方式需要有唯一索引,通过唯一索引去判断是否冲突,有冲突就会更新,没有冲突就会插入数据。

<!-- 批量插入或者更新 -->
    <insert id="saveOrUpdateBatch" keyProperty="id" useGeneratedKeys="true">
        insert into hh_chain_customer_info(id,description, create_time, update_time, service_id, name, code, req_mode,
        req_api, sign_policy)
        values
        <foreach collection="entities" item="entity" separator=",">
            (#{entity.id},#{entity.description}, #{entity.createTime}, #{entity.updateTime}, #{entity.serviceId},
            #{entity.name},
            #{entity.code}, #{entity.reqMode}, #{entity.reqApi}, #{entity.signPolicy})
        </foreach>
        on duplicate key update
        description = values(description),
        create_time = values(create_time),
        update_time = values(update_time),
        service_id = values(service_id),
        name = values(name),
        code = values(code),
        req_mode = values(req_mode),
        req_api = values(req_api),
        sign_policy = values(sign_policy)
    </insert>

1.持久层代码示例

package com.hhmt.delivery.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hhmt.delivery.pojo.entity.HhChainCustomerParams;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;
import java.util.List;

/**
 * 链路客户参数Mapper接口
 *
 * @author huachun
 * @date 2023-01-31
 */
@Mapper
public interface HhChainCustomerParamsMapper extends BaseMapper<HhChainCustomerParams> {
    

    boolean insertOrUpdateBatch(@Param("entities") Collection<HhChainCustomerParams> hhChainCustomerParams);
}

2.服务实现类

package com.hhmt.delivery.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hhmt.delivery.core.utils.DateUtils;
import com.hhmt.delivery.mapper.HhChainCustomerParamsMapper;
import com.hhmt.delivery.pojo.entity.HhChainCustomerParams;
import com.hhmt.delivery.service.IHhChainCustomerParamsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;

/**
 * 链路客户参数Service业务层处理
 *
 * @author huachun
 * @date 2023-01-31
 */
@Service
public class HhChainCustomerParamsServiceImpl extends ServiceImpl<HhChainCustomerParamsMapper, HhChainCustomerParams> implements IHhChainCustomerParamsService {
    @Autowired
    private HhChainCustomerParamsMapper hhChainCustomerParamsMapper;    

    @Override
    public boolean saveOrUpdateBatch(Collection<HhChainCustomerParams> entityList) {
        return hhChainCustomerParamsMapper.insertOrUpdateBatch(entityList);
    }
}

此时sql日志:

拦截的sql ==>: com.hhmt.delivery.mapper.HhChainCustomerInfoMapper.saveOrUpdateBatch:insert into hh_chain_customer_info(id,description, create_time, update_time, service_id, name, code, req_mode, req_api, sign_policy) values (1621028577047281666,, , , , '111111111111', , , , ) on duplicate key update description = values(description), create_time = values(create_time), update_time = values(update_time), service_id = values(service_id), name = values(name), code = values(code), req_mode = values(req_mode), req_api = values(req_api), sign_policy = values(sign_policy)
sql耗时 ==>: 14 毫秒
类型 ==> INSERT
拦截的sql ==>: com.hhmt.delivery.mapper.HhChainCustomerInfoMapper.saveOrUpdateBatch:insert into hh_chain_customer_info(id,description, create_time, update_time, service_id, name, code, req_mode, req_api, sign_policy) values (1621028577047281666,, , , , 'dsfasdfadf', , , , ) on duplicate key update description = values(description), create_time = values(create_time), update_time = values(update_time), service_id = values(service_id), name = values(name), code = values(code), req_mode = values(req_mode), req_api = values(req_api), sign_policy = values(sign_policy)
sql耗时 ==>: 0 毫秒
类型 ==> INSERT
拦截的sql ==>: com.hhmt.delivery.mapper.HhChainCustomerInfoMapper.saveOrUpdateBatch:insert into hh_chain_customer_info(id,description, create_time, update_time, service_id, name, code, req_mode, req_api, sign_policy) values (,, , , , 'dsfasdfadf', , , , ) on duplicate key update description = values(description), create_time = values(create_time), update_time = values(update_time), service_id = values(service_id), name = values(name), code = values(code), req_mode = values(req_mode), req_api = values(req_api), sign_policy = values(sign_policy)
sql耗时 ==>: 0 毫秒

个人感觉这样效率更改更方便,值得推荐

4.注意

on udplicate key update后的内容表示,主键存在时则执行更新操作,需要注意的是insert字段中需要含有唯一性字段(主键索引或唯一索引)

原文参考 mysql插入或更新_w_t_y_y的博客-CSDN博客_mysql 插入更新

5.常见问题 

详细后续补充~文章来源地址https://www.toymoban.com/news/detail-443280.html

到了这里,关于批量插入或更新数据(MyBatis-plus框架)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mybatis-Plus的SQL注入器实现批量插入/修改,效率比较

    mysql支持一条sql语句插入多条数据。但是Mybatis-Plus中默认提供的saveBatch、updateBatchById方法并不能算是真正的批量语句,而是遍历实体集合执行INSERT_ONE、UPDATE_BY_ID语句。 mybatis-plus虽然做了分批请求、一次提交的处理。但如果jdbc不启用配置rewriteBatchedStatements,那么批量提交的s

    2024年02月11日
    浏览(50)
  • Mybatis-plus通过其他字段批量更新或新增

    根据某个或者多个非ID字段进行批量更新 示例通过名称与id两个字段更新 引用mybatis-plus根据某个指定字段批量更新数据库 通过其他字段批量更新或新增

    2024年02月12日
    浏览(50)
  • No Spring环境Mybatis-Plus批量插入并返回主键的两种方式

    批量插入,可以把Mybatis-Plus看作是Mybatis加强版;故Mybatis中的相关操作都可以在Mybatis-Plus中使用;在mysql数据库中支持批量插入,所以只要配置useGeneratedKeys和keyProperty就可以批量插入并返回主键了。 下面是批量插入的Dao层接口    一注解方式:      直接撸代码:      第二种: XML方

    2024年02月09日
    浏览(35)
  • spring boot集成mybatis-plus——Mybatis Plus 批量 Insert_新增数据(图文讲解)

     更新时间 2023-01-10 16:02:58 大家好,我是小哈。 本小节中,我们将学习如何通过 Mybatis Plus 实现 MySQL 批量插入数据。 先抛出一个问题:假设老板给你下了个任务,向数据库中添加 100 万条数据,并且不能耗时太久! 通常来说,我们向 MySQL 中新增一条记录,SQL 语句类似如下:

    2024年02月04日
    浏览(50)
  • Mybatis-Plus批量添加或修改数据的三种方式

    提供的方法 是遍历每一个元素,判断主键是否存在,如果存在则做更新,不存在添加 先获取表中所有的主键 ,然后 判断是否已存在,存在更新,不存在添加 on duplicate key update 是Mysql特有的语法,如下图所示,表中id 为主键 再插入id为1的数据,则提示主键已存在 改成如下

    2024年02月06日
    浏览(45)
  • Mybatis-plus批量操作

            使用Mybatis-plus可以很方便的实现批量新增和批量修改,不仅比自己写foreach遍历方便很多,而且性能也更加优秀。但是Mybatis-plus官方提供的批量修改和批量新增都是根据id来修改的,有时候我们需求其他字段,所以就需要我们自己修改一下。         在Mybatis-plus的IS

    2024年02月11日
    浏览(41)
  • 【Mybatis-Plus】mybatisplus更新时,实体字段为空,数据库不更新的解决方案

    项目技术栈:jdk (1.8) + spring boot (2.1.0) + mybatis-plus (3.5.1) 数据库: MySQL 字段类型:varchar 和 Integer 从前端传过来的数据实体字段, convertType 和 step 设为null时,使用mybatis-plus 的 updateById方法往数据库中更新时,这两个字段不更新,数据不为空可以插入。 mybatis-plus在更新的时候做

    2024年01月16日
    浏览(63)
  • mybatis-plus的批量新增insertBatchSomeColumn

    MyBatis-Plus 是基于 MyBatis 进行封装的一套优秀的持久层框架,它提供了丰富的便捷操作方法和强大的代码生成器,大大简化了 MyBatis 的使用。在 MyBatis-Plus 中,我们可以使用 insertBatchSomeColumn 方法来实现批量新增指定字段的操作。 mybatis-plus 的  IService 接口  默认提供   saveBat

    2024年02月01日
    浏览(42)
  • mybatis-plus批量保存异常及效率优化

    最近基于自己公司内部服务维护,发现其中调度中心近期出现不少错误日志,但是该任务却是正常执行,生成的报表数据也是正常的,所以很多天没有发现问题 这就匪夷所思了,    经仔细排查发现,是触发了feign超时hystrix熔断器机制 也就是说子服务出现了执行时间过长的

    2024年01月16日
    浏览(35)
  • mybatis-plus 根据指定字段 批量 删除/修改

    mybatis-plus 提供了根据id批量更新和修改的方法,这个大家都不陌生 但是当表没有id的时候怎么办) 这个就不说了,就是因为不想手写SQL 所以才有这篇博客 mybatis plus 的 executeBatch 参考 mybatis plus 的updateBatchById 方法. 调用处: 接口 重写方法 实现 这种写法其实批量的效率还是比较慢的

    2024年02月13日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包