分享

Mybatis-plus---的批量插入_mybatisplus批量插入

 ygabg2pf4rzd4x 2023-08-03 发布于福建


批量插入

一、继承IService(伪批量)

二、insertBatchSomeColumn


Mybatis-plus很强,为我们诞生了极简CURD操作,但对于数据批量操作,显然默认提供的insert方法是不够看的了,于是它和它来了!!! Mybatis-plus提供的两种插入方式

        继承IService(伪批量)

        insertBatchSomeColumn 

一、继承IService(伪批量)

在Mapper继承BaseMapper<T>

  1. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2. import com.example.demo.entity.UserStudy;
  3. import org.apache.ibatis.annotations.Mapper;
  4. @Mapper
  5. public interface UserStudyMapper extends BaseMapper<UserStudy> {
  6. }

在Service中继承IService<T>

  1. import com.baomidou.mybatisplus.extension.service.IService;
  2. import com.example.demo.entity.UserStudy;
  3. /********************************************************************************
  4. ** @author : ZYJ
  5. ** @date :2023/04/20
  6. ** @description :厂长老婆催的睡觉了-批量插入Service
  7. *********************************************************************************/
  8. public interface UserStudyService extends IService<UserStudy> {
  9. }

在Service实现类继承ServiceImpl<M,T>

  1. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  2. import com.example.demo.entity.UserStudy;
  3. import com.example.demo.mapper.UserStudyMapper;
  4. import org.springframework.stereotype.Service;
  5. import javax.annotation.Resource;
  6. /********************************************************************************
  7. ** @author : ZYJ
  8. ** @date :2023/04/04
  9. ** @description :厂长加班写代码-批量插入
  10. *********************************************************************************/
  11. @Service
  12. public class UserStudyServiceImpl extends ServiceImpl<UserStudyMapper, UserStudy> implements UserStudyService {
  13. @Resource
  14. private UserStudyMapper userStudyMapper;
  15. }

测试代码,调用IService的saveBatch方法

  1. /*
  2. *批量插入
  3. */
  4. @Override
  5. public void greatMany() {
  6. List<UserStudy> userStudyList = new ArrayList<>();
  7. UserStudy userStudy1 = new UserStudy();
  8. userStudy1.setName("张三");
  9. UserStudy userStudy2 = new UserStudy();
  10. userStudy2.setName("李四");
  11. userStudyList.add(userStudy1);
  12. userStudyList.add(userStudy2);
  13. //调用IService的saveBatch方法
  14. this.saveBatch(userStudyList);
  15. }

Mybatis-plus的SQL日志打印在配置文件application.yml配置

  1. mybatis-plus:
  2. configuration:
  3. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志
  4. # log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl #关闭sql日志

测试结果,代码执行打印了两条SQL,所以可以看得出saveBatch底层也是遍历循环完成 

saveBatch方法分析

底层也是通过for来完成,默认是一个事务一次提交1000条数据,点击进入saveBatch可以看到, 也可以自定义每次提交多少条,自定义如下

  1. //调用IService的saveBatch方法
  2. this.saveBatch(userStudyList,2000);

二、insertBatchSomeColumn

自定义SQL注入器

  1. import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  2. import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
  3. import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
  4. import java.util.List;
  5. /********************************************************************************
  6. ** @author : ZYJ
  7. ** @date :2023/03/09
  8. ** @description :厂长加班写代码-批量插入SQL注入器
  9. *********************************************************************************/
  10. public class InsertBatchSqlInjector extends DefaultSqlInjector {
  11. @Override
  12. public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
  13. List<AbstractMethod> methodList = super.getMethodList(mapperClass);
  14. methodList.add(new InsertBatchSomeColumn()); //添加InsertBatchSomeColumn方法
  15. return methodList;
  16. }
  17. }

把SQL注入器交给Spring

  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class MybatisPlusConfig {
  5. /********************************************************************************
  6. ** @author : ZYJ
  7. ** @date :2023/04/14
  8. ** @description :注入配置
  9. *********************************************************************************/
  10. @Bean
  11. public InsertBatchSqlInjector easySqlInjector () {
  12. return new InsertBatchSqlInjector();
  13. }
  14. }

到此定义完毕,在Mapper中生成insertBatchSomeColumn(必须是这个方法名)方法,你就可以撒手不管了,直接调用就行,或者直接在ServiceImpl通过Mapper调用insertBatchSomeColumn,然后ALT+回车生成此方法。

  1. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2. import com.example.demo.entity.UserStudy;
  3. import org.apache.ibatis.annotations.Mapper;
  4. import org.apache.ibatis.annotations.Param;
  5. import java.util.List;
  6. @Mapper
  7. public interface UserStudyMapper extends BaseMapper<UserStudy> {
  8. void insertBatchSomeColumn(@Param("list") List<UserStudy> userStudyList);
  9. }

测试代码,调用insertBatchSomeColumn方法

  1. @Resource
  2. private UserStudyMapper userStudyMapper;
  3. /*
  4. *批量插入
  5. */
  6. @Override
  7. public void greatMany() {
  8. List<UserStudy> userStudyList = new ArrayList<>();
  9. UserStudy userStudy1 = new UserStudy();
  10. userStudy1.setName("张三");
  11. UserStudy userStudy2 = new UserStudy();
  12. userStudy2.setName("李四");
  13. userStudyList.add(userStudy1);
  14. userStudyList.add(userStudy2);
  15. //调用insertBatchSomeColumn方法
  16. userStudyMapper.insertBatchSomeColumn(userStudyList);
  17. //调用IService的saveBatch方法
  18. //this.saveBatch(userStudyList,2000);
  19. }

测试结果,代码执行打印一条SQL,所以可以看出是一条SQL便新增完成

注意:SQL有语句长度限制,在MySQL中被参数max_allowed_packet限制,默认为1M,如果拼接长度超过此限制就会报错,两种解决方式,一个是调整MySQL的max_allowed_packet 限制,另一个则是通过代码控制每次的提交数量。

通过代码控制每次提交数量,模拟造五条数据,每次提交两条数据

  1. /*
  2. *批量插入
  3. */
  4. @Override
  5. public void greatMany() {
  6. List<UserStudy> userStudyList = new ArrayList<>();
  7. UserStudy userStudy1 = new UserStudy();
  8. userStudy1.setName("张三");
  9. UserStudy userStudy2 = new UserStudy();
  10. userStudy2.setName("李四");
  11. UserStudy userStudy3 = new UserStudy();
  12. userStudy3.setName("王五");
  13. UserStudy userStudy4 = new UserStudy();
  14. userStudy4.setName("赵六");
  15. UserStudy userStudy5 = new UserStudy();
  16. userStudy5.setName("小红");
  17. userStudyList.add(userStudy1);
  18. userStudyList.add(userStudy2);
  19. userStudyList.add(userStudy3);
  20. userStudyList.add(userStudy4);
  21. userStudyList.add(userStudy5);
  22. //创建入库的list
  23. List<UserStudy> userStudyCount = new ArrayList<>();
  24. for (int i = 0; i < userStudyList.size(); i++) {
  25. //调用insertBatchSomeColumn方法
  26. userStudyCount.add(userStudyList.get(i));
  27. //控制每次提交数量
  28. if(userStudyCount.size()==2){
  29. userStudyMapper.insertBatchSomeColumn(userStudyCount);
  30. //将入库的list清空重新新增
  31. userStudyCount.clear();
  32. }
  33. }
  34. //将list中size不够2的数据在此处新增
  35. userStudyMapper.insertBatchSomeColumn(userStudyCount);
  36. //调用IService的saveBatch方法
  37. //this.saveBatch(userStudyList,2000);
  38. }

结果分析,五条数据应该请求三次新增,打印三条SQL,完美结束

总结:默认的insert的方法对寻常业务来说是非常之高效,但对于批量数据的产生确实灾难性的,就是慢,很慢,巨慢,IService的saveBatch方法优于默认的insert方法,但是我选通过SQL注入器的方法insertBatchSomeColumn。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多