MyBatis的五种批量插入详解

 更新时间:2023年08月25日 09:10:24   作者:谁是黄黄  
这篇文章主要介绍了MyBatis的五种批量插入详解,MyBatis是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低,需要的朋友可以参考下

MyBatis

MyBatis是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低

用mybatis进行开发,需要手动编写SQL语句。而全自动的ORM框架,如hibernate,则不需要编写SQL语句。

用hibernate开发,只需要定义好ORM映射关系,就可以直接进行CRUD操作了。

由于mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialect),所以mybatis的数据库无关性低。

一.直接循环插入

@RestController
@RequestMapping("/mybatis3/user")
@RequiredArgsConstructor
public class UserController {
    private final IUserService iUserService;
    @GetMapping("/one")
    public Long one(){
       return iUserService.add();
    }
}
  Long add();
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    private final UserMapper userMapper;
    @Override
    public Long add() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            User user = new User();
            user.setUsername("name"+i);
            user.setPassword("password"+i);
            userMapper.insertUsers(user);
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+( end - start ) + "ms");
        return (end-start);
    }
    }
 Integer insertUsers(User user);
 <insert id="insertUsers" >
        insert into user(username,password)
        values (#{username}, #{password})
    </insert>

最终耗时:14s多

在这里插入图片描述

二.关闭MySql自动提交,手动进行循环插入提交

@RestController
@RequestMapping("/mybatis3/user")
@RequiredArgsConstructor
public class UserController {
    private final IUserService iUserService;
        @GetMapping("/one")
    public Long one(){
       return iUserService.add();
    }
}
 Long add2();
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    private final UserMapper userMapper;
//    手动开启sql的批量提交
    private final   SqlSessionTemplate sqlSessionTemplate;
    @Override
    public Long add2(){
        //关闭自动提交
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            User user = new User();
            user.setUsername("name"+i);
            user.setPassword("password"+i);
            mapper.insertUsers(user);
        }
        //自动提交SQL
        sqlSession.commit();
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+( end - start ) + "ms");
        return (end-start);
    }
    }

平均:0.12s

在这里插入图片描述

第三种:用List集合的方式插入数据库(推荐)

@RestController
@RequestMapping("/mybatis3/user")
@RequiredArgsConstructor
public class UserController {
    private final IUserService iUserService;
       @GetMapping("/one3")
    public Long one3(){
        return iUserService.add3();
    }
}
  Long add3();
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    private final UserMapper userMapper;
  @Override
    public Long add3(){
        long start = System.currentTimeMillis();
        List<User> userList = new ArrayList<>();
        User user;
        for (int i = 0; i < 10000; i++) {
            user = new User();
            user.setUsername("name"+i);
            user.setPassword("password"+i);
            userList.add(user);
        }
        userMapper.insertUsersThree(userList);
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+( end - start ) + "ms");
        return (end-start);
    }
    }
 Integer insertUsersThree(List<User> userList);
<insert id="insertUsersThree">
        insert into user(username,password)
        values
        <foreach collection="userList" item="user" separator=",">
            (#{user.username},#{user.password})
        </foreach>
    </insert>

第四种: MyBatis-Plus提供的SaveBatch方法

@RestController
@RequestMapping("/mybatis3/user")
@RequiredArgsConstructor
public class UserController {
    private final IUserService iUserService;
@GetMapping("/one4")
    public Long one4(){
        return iUserService.add4();
    }
}
  Long add4();
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    private final UserMapper userMapper;
@Override
    public Long add4() {
        long start = System.currentTimeMillis();
        List<User> userList= new ArrayList<>();
        User user ;
        for (int i = 0; i < 10000; i++) {
            user = new User();
            user.setUsername("name"+i);
            user.setPassword("password"+i);
            userList.add(user);
        }
        saveBatch(userList);
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+( end - start ) + "ms");
        return (end-start);
    }
    }

直接报错:

在这里插入图片描述

看报错信息:

长串:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: com.huang.mybatis3.mapper.UserMapper.insert (batch index #1) failed. Cause: java.sql.BatchUpdateException: Data truncation: Out of range value for column ‘id’ at row 1 ; Data truncation: Out of range value for column ‘id’ at row 1; nested exception is java.sql.BatchUpdateException: Data truncation: Out of range value for column ‘id’ at row 1] with root cause

短串:Data truncation: Out of range value for column ‘id’ at row 1

翻译一下:

在这里插入图片描述

可以发现就是我们的id超出范围:

在这里插入图片描述

int类型改为bigint即可

故此我们可以得出一个结论:设置数据库id的时候设置为bigint还是蛮好的哈

平均时间:0.2s

在这里插入图片描述

第五种 MyBatis-Plus提供的InsertBatchSomeColumn方法(推荐)

InsertBatchSomeColumn方法了解

在这里插入图片描述

这个类的注解就写的很明白

扩展这个InsertBatchSomeColumn方法

@Slf4j
public class EasySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        // 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        log.info("扩展的getMethodList方法被框架调用了");
        return methodList;
    }
}

扩展的方法注入bean容器

/**
 * @author Stone
 * @date 2023/1/3
 * @apiNote
 */
@Configuration
public class MybatisPlusConfig {
    @Bean
    public  EasySqlInjector sqlInjector(){
        return new EasySqlInjector();
    }
}

创建一个Mapper去实现我们的扩展的飞方法

public interface EasySqlInjectMapper<T> extends BaseMapper<T> {
    /**
     * 批量插入 仅适用于mysql
     *
     * @param entityList 实体列表
     * @return 影响行数
     */
    Integer insertBatchSomeColumn(Collection<T> entityList);
}

业务层

 @Override
    public Long add5() {
        long start = System.currentTimeMillis();
        List<User> userList= new ArrayList<>();
        User user ;
        for (int i = 0; i < 10000; i++) {
            user = new User();
            user.setUsername("name"+i);
            user.setPassword("password"+i);
            userList.add(user);
        }
        userMapper.insertBatchSomeColumn(userList);
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+( end - start ) + "ms");
        return (end-start);
    }

耗时: 0.2 s

在这里插入图片描述

到此这篇关于MyBatis的五种批量插入详解的文章就介绍到这了,更多相关MyBatis的批量插入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Jenkins自动打包并部署docker环境的操作过程

    基于Jenkins自动打包并部署docker环境的操作过程

    这篇文章主要介绍了基于Jenkins自动打包并部署docker环境,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • JavaStream将List转为Map示例

    JavaStream将List转为Map示例

    这篇文章主要为大家介绍了JavaStream将List转为Map示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 关于IDEA创建spark maven项目并连接远程spark集群问题

    关于IDEA创建spark maven项目并连接远程spark集群问题

    这篇文章主要介绍了IDEA创建spark maven项目并连接远程spark集群,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • springboot日志没有记录异常问题及解决

    springboot日志没有记录异常问题及解决

    在Spring Boot项目中,定时任务在服务器上运行时报错但未记录日志,本地运行时控制台能打印报错信息,但日志中无记录,问题出在报错发生在线程池中,通过继承ThreadPoolExecutor并重写afterExecute方法,可以将异常信息记录到日志中
    2025-02-02
  • springboot集成es插入和查询的简单使用示例详解

    springboot集成es插入和查询的简单使用示例详解

    这篇文章主要介绍了springboot集成es 插入和查询的简单使用,本文分步骤结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • springboot使用定时器@Scheduled不管用的解决

    springboot使用定时器@Scheduled不管用的解决

    这篇文章主要介绍了springboot使用定时器@Scheduled不管用的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java中RocketMQ使用方法详解

    Java中RocketMQ使用方法详解

    这篇文章主要介绍了RocketMQ和Kafka在SpringBoot中的使用方法,以及如何保证消息队列的顺序性、可靠性以及幂等性,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-02-02
  • java字符串日期类Date和Calendar相互转化及相关常用方法

    java字符串日期类Date和Calendar相互转化及相关常用方法

    Java语言的Calendar(日历),Date(日期),和DateFormat(日期格式)组成了Java标准的一个基本但是非常重要的部分,下面这篇文章主要给大家介绍了关于java字符串日期类Date和Calendar相互转化及相关常用方法的相关资料,需要的朋友可以参考下
    2023-12-12
  • SpringBoot如何自定义starter

    SpringBoot如何自定义starter

    这篇文章主要介绍了SpringBoot如何自定义starter,Springboot的出现极大的简化了开发人员的配置,而这之中的一大利器便是springboot的starter,starter是springboot的核心组成部分,下面来看看集体引用过程吧
    2022-01-01
  • 使用springboot aop记录接口请求的参数及响应

    使用springboot aop记录接口请求的参数及响应

    该文章介绍了如何使用SpringAOP的切面注解,如@Before和@AfterReturning,来记录Controller层的方法输入参数和响应结果,还讨论了@Around注解的灵活性,允许在方法执行前后进行更多控制,需要的朋友可以参考下
    2024-05-05

最新评论