mybatis批量插入、mybatis-plus批量插入、mybatis实现insertList、mybatis ...

打印 上一主题 下一主题

主题 507|帖子 507|积分 1521

众所周知,mybatisplus提供的BaseMapper里只有单条插入的方法,没有批量插入的方法,
而在Service层的批量插入并不是真的批量插入,实际上是遍历insert,但也不是一次insert就一次IO,而是到一定数目才会去IO一次,性能不是很差,但也不够好。
怎么才气实现真正的批量插入呢?
这里是mybatisplus官方的演示仓库,可以先去了解一下。
一、mybatis新增批量插入

1.1、引入依赖

本文基于mybatis-plus3.5.0举行讲解,不同的版本写法稍微有点不同。
  1. <!--mybatis-plus-->
  2. <dependency>
  3.      <groupId>com.baomidou</groupId>
  4.      <artifactId>mybatis-plus-boot-starter</artifactId>
  5.      <version>3.5.0</version>
  6. </dependency>
复制代码
1.2、自定义通用批量插入Mapper

1.新建一个InsertListMapper文件,提供insertList方法,后续需要用到批量插入的dao继续该Mapper即可拥有批量插入接口。
  1. import org.apache.ibatis.annotations.Param;
  2. import java.util.List;
  3. /**
  4. * 通用Mapper接口,特殊方法,批量插入,支持批量插入的数据库都可以使用,例如mysql,h2等
  5. *
  6. * @param <T> 不能为空
  7. * @author
  8. */
  9. public interface InsertListMapper<T> {
  10.     /**
  11.      * 批量插入,支持批量插入的数据库可以使用,例如MySQL,H2等
  12.      * <p>
  13.      * 注意:
  14.      * 1.若实体类中设置了@TableId注解,则需要设置value值  如:@TableId(value = "id")
  15.      * 2.若建表语句中设置了default, 需要在插入时手动设置默认值,否则存储的是null。
  16.      * 如:delete_flag tinyint default 0 comment '删除标志 0-未删除 1-已删除',这种需要在insert的时候设置实体类改字段值。setDeleteFlag(0)
  17.      * <p>
  18.      *
  19.      * @param recordList
  20.      * @return
  21.      */
  22.     int insertList(@Param("list") List<T> recordList);
  23. }
复制代码
1.3、把通用方法注册到mybatisplus注入器中

  1. import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  2. import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
  3. import com.baomidou.mybatisplus.core.metadata.TableInfo;
  4. import org.springframework.stereotype.Component;
  5. import java.util.List;
  6. /**
  7. * 添加Sql注入方法,支持空字段更新
  8. */
  9. @Component
  10. public class CustomerSqlInjector extends DefaultSqlInjector {
  11.     @Override
  12.     public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo){
  13.         List<AbstractMethod> methodList=super.getMethodList(mapperClass, tableInfo);
  14.         //注册自定义方法
  15.         //注意:InsertList中的name需要与xxxMapper中的方法名一致,即insertList
  16.         methodList.add(new InsertList("insertList"));
  17.         return methodList;
  18.     }
  19. }
复制代码
关键的一句在于methodList.add(new InsertList("insertList"));,意为注册一个新的方法叫insertList,详细实如今InsertList类。
1.4、实现InsertList类

  1. import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  2. import com.baomidou.mybatisplus.core.metadata.TableInfo;
  3. import org.apache.ibatis.executor.keygen.KeyGenerator;
  4. import org.apache.ibatis.executor.keygen.NoKeyGenerator;
  5. import org.apache.ibatis.mapping.MappedStatement;
  6. import org.apache.ibatis.mapping.SqlSource;
  7. import java.util.Collections;
  8. public class InsertList extends AbstractMethod {
  9.     public InsertList(String name) {
  10.         super(name);
  11.     }
  12.     @Override
  13.     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
  14.         KeyGenerator keyGenerator = new NoKeyGenerator();
  15.         SqlSource sqlSource = languageDriver.createSqlSource(configuration, getBatchInsertSql(tableInfo,modelClass), Collections.class);
  16.         return this.addInsertMappedStatement(mapperClass,modelClass,"insertList",sqlSource,keyGenerator,null,null);
  17.     }
  18.     private String getBatchInsertSql(TableInfo tableInfo, Class<?> modelClass){
  19.         String batchInsertSql="<script> INSERT INTO %s (%s) values %s</script>";
  20.         //要插入的字段 即insert into table(要插入的字段) values
  21.         StringBuilder insertColumnSql=new StringBuilder();
  22.         insertColumnSql.append(tableInfo.getKeyColumn()).append(",");
  23.         StringBuilder valueSql=new StringBuilder();
  24.         valueSql.append("<foreach collection='list' item='item' open='(' separator='),(' close=')' >\n");
  25.         valueSql.append("#{item."+tableInfo.getKeyProperty()+"},");
  26.         tableInfo.getFieldList().forEach(x->{
  27.             insertColumnSql.append(x.getColumn()).append(",");
  28.             valueSql.append("#{item."+x.getProperty()+"},");
  29.         });
  30.         insertColumnSql.delete(insertColumnSql.length()-1,insertColumnSql.length());
  31.         valueSql.delete(valueSql.length()-1,valueSql.length());
  32.         valueSql.append("</foreach>");
  33.         return  String.format(batchInsertSql,tableInfo.getTableName(),insertColumnSql,valueSql);
  34.     }
  35. }
复制代码
1.5、需要批量插入的dao层继续批量插入Mapper

  1. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  2. import com.demo.common.mapper.InsertListMapper;
  3. import com.demo.entity.User;
  4. /**
  5. * @Entity generator.domain.User
  6. */
  7. public interface UserMapper extends BaseMapper<User>, InsertListMapper<User> {
  8. }
复制代码
以上代码全都放在gitee仓库,详情见:
代码仓库地点
二、大概遇到的题目

2.1、Invalid bound statement

  1. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.demo.mapper.User1Mapper.insertList
  2.         at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)
  3.         at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.<init>(MybatisMapperMethod.java:50)
  4.         at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.lambda$cachedInvoker$0(MybatisMapperProxy.java:111)
  5.         at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
  6.         at com.baomidou.mybatisplus.core.toolkit.CollectionUtils.computeIfAbsent(CollectionUtils.java:115)
  7.         at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.cachedInvoker(MybatisMapperProxy.java:98)
  8.         at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
  9.         at com.sun.proxy.$Proxy70.insertList(Unknown Source)
  10.         at com.demo.User1Test.test1(User1Test.java:50)
  11.         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  12.         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  13.         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  14.         at java.lang.reflect.Method.invoke(Method.java:498)
  15.         at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
  16.         at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  17.         at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
  18.         at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
复制代码
办理方法: :https://blog.csdn.net/weixin_49114503/article/details/140645048






参考文章:https://blog.csdn.net/m0_51390969/article/details/134730527
https://blog.csdn.net/m0_63297646/article/details/131843517

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

雁过留声

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表