Mybatis Plus 批量插入

文章介绍了如何使用MybatisPlus的默认`saveBatch()`方法进行批量数据插入,但发现该方法在处理大量数据时性能低下。作者参考了网上的优化策略,将执行1万条数据的时间从59秒降低到2秒左右。优化主要通过自定义分批插入的策略实现,提高了批量操作的效率。
摘要由CSDN通过智能技术生成

Mybatis Plus 默认提供了一个批量保存数据到数据库的方法,也就是 IService#saveBatch() 接口方法,其实质是遍历然后逐个insert ,如果插入数据过多会影响性能,下图为使用此方法执行1万条时间 59秒

时间上的确是太久了,然后参考网上一些优秀的人写的文章,调整优化到了2秒左右

下面是参考代码:

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

public interface BaseSqlMapper<T> extends BaseMapper<T> {

    /**
     * 默认批次提交数量
     */
    int DEFAULT_BATCH_SIZE = 1000;

    /**
     * 以下定义的 4个 default method, copy from {@link com.baomidou.mybatisplus.extension.toolkit.ChainWrappers}
     */
    default QueryChainWrapper<T> queryChain() {
        return new QueryChainWrapper<>(this);
    }

    default LambdaQueryChainWrapper<T> lambdaQueryChain() {
        return new LambdaQueryChainWrapper<>(this);
    }

    default UpdateChainWrapper<T> updateChain() {
        return new UpdateChainWrapper<>(this);
    }

    default LambdaUpdateChainWrapper<T> lambdaUpdateChain() {
        return new LambdaUpdateChainWrapper<>(this);
    }

    /**
     * 批量新增数据,自选字段 insert. 自动按每批1000插入数据库
     * 此填充不会填充 FieldFill.UPDATE 的字段。
     * 注意数据库默认更新的字段也需要手工设置
     *
     * @see MySqlInjector#getMethodList(Class)
     * @param entityList 数据
     * @return 插入条数
     */
    @Transactional(rollbackFor = Exception.class)
    default int insertBatch(List<T> entityList) {
        return this.insertBatchSomeColumn(entityList, DEFAULT_BATCH_SIZE);
    }

    /**
     * 批量新增数据,自选字段 insert
     * 不会分批插入,需要分批请调用方法insertBatch或者 insertBatchSomeColumn(List<T> entityList, int size)
     * 此填充不会填充 FieldFill.UPDATE 的字段。
     * 注意数据库默认更新的字段也需要手工设置
     *
     * @see MySqlInjector#getMethodList(Class)
     * @param entityList 数据
     * @return 插入条数
     */
    int insertBatchSomeColumn(List<T> entityList);

    /**
     * 分批插入。每次插入
     * @param entityList 原实体对象
     * @param size 分批大小
     * @return 总插入记录
     */
    @Transactional(rollbackFor = Exception.class)
    default int insertBatchSomeColumn(List<T> entityList, int size) {
        if (CollUtil.isEmpty(entityList)) {
            return 0;
        }
        List<List<T>> split = CollUtil.split(entityList, size);
        return split.stream().mapToInt(this::insertBatchSomeColumn).sum();

    }

}

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;

import java.util.List;

public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 例: 不要指定了 update 填充的字段
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }
}

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.parsers.DynamicTableNameParser;
import com.baomidou.mybatisplus.extension.parsers.ITableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.hieasy.comm.constant.Constants;
import com.hieasy.comm.utils.security.Guard;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MP配置
 */
@Configuration
public class MybatisplusConfig {


    @Resource
    private HttpServletRequest request;

    /*分页插件*/
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setLimit(-1);
        return  paginationInterceptor;
    }


    /**
     * 自定义内置选装件
     *
     * @return
     */
    @Bean
    public MySqlInjector sqlInjector() {
        return new MySqlInjector();
    }



}

import com.hieasy.pos.common.config.BaseSqlMapper;
import com.hieasy.pos.domain.promote.comm.CxCmKehu;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface CxCmKehuMapper extends BaseSqlMapper<CxCmKehu> {



}

    protected void insertCxKehu(Integer aid, Integer cxlx, Long pid, List<CxCmKehu> kehuList){
         for(CxCmKehu cxkh:kehuList){
             cxkh.setAccountid(aid);
             cxkh.setCxlx(cxlx);
             cxkh.setPid(pid);
//             cxCmKehuMapper.insert(cxkh);
         }
        cxCmKehuMapper.insertBatchSomeColumn(kehuList);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值