mybatis使用多线程批量插入数据

昨天在项目中有一个excel导表的操作,于是就想着用多线程插入数据。网上找了下mabayis多线程插入数据,看了很多都是配置的xml,但我不是很喜欢写xml.....于是自己手写了一个,代码可能不是很优雅,但还是记录一下.不多说,直接上代码。

 

controller,和dao就不放了,

主要是service层

 @Override
    public int upload(Long paperId,List<InterviewProblem> interviewProblems) {
        //面试卷加题
        InterviewPaper interviewPaper = interviewPaperMapper.selectByPrimaryKey(paperId);
        interviewPaper.setCount(interviewPaper.getCount()+interviewProblems.size());
        interviewPaperMapper.updateByPrimaryKey(interviewPaper);
        //写入题库
        //开启一个线程池,3个线程
        ExecutorService executor = Executors.newFixedThreadPool(3);
        //计数器,初始为需要插入的数据集的条数
        CountDownLatch countDownLatch = new CountDownLatch(interviewProblems.size());
        int i=0;
        //出现异常返回
        final int[] flag = {0};
        try{
            //每条数据都写进去
            for(;i<interviewProblems.size();i++) {
                int index = i;
                executor.execute(() -> {
                    try{
                        //插入业务
                        InterviewProblem interviewProblem = interviewProblems.get(index);
                        interviewProblem.setId(idWorker.nextId()+"");
                        interviewProblem.setInterviewPaperId(paperId);
                        interviewProblemMapper.insert(interviewProblem);
                    }catch(Exception e){
                        //写入日志
                        log.error("第"+index+"条出错  "+e.getMessage());
                        //修改异常标志
                        flag[0] = 1;
                        throw new RuntimeException("第"+index+"条出错  ");
                    }finally {
                        //计数器减一
                        countDownLatch.countDown();
                    }
                });
            }
        //如果计数器不为0,就等待,这个如果计数不正确,主线程就会先执行,相当于数据还没有插完,就返回成功给前端.
            countDownLatch.await();
        }catch(Exception e){

        }finally {
            //关闭线程池
            executor.shutdown();
        }
        //判断是否异常
        if(flag[0] == 1)
            return 1;
        else
            return 0;
    }

这里的线程池也可以换成

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,5,1,TimeUnit.SECONDS,new LinkedBlockingQueue<>(3));

如果不了解多线程和lamda表达式..

用我抽取的模板就行

  public static void main(String[] args) {
        int dataSize = 10000;//数据的条数
        int threadNumber = 10;//开启的线程数
        CountDownLatch countDownLatch = new CountDownLatch(dataSize);
        int i=0;
        ExecutorService executor = Executors.newFixedThreadPool(threadNumber);
        //出现异常返回
        final int[] flag = {0};
        try{
            for(;i<dataSize;i++) {
                int index = i;
                executor.execute(() -> {
                    try{
                        //你的业务逻辑
                        System.out.println("第"+index+"成功");
                    }catch(Exception e){
                        //写入日志
                        log.error("第"+index+"条出错  "+e.getMessage());
                        flag[0] = 1;
                        throw new RuntimeException("第"+index+"条出错  ");
                    }finally {
                        countDownLatch.countDown();
                    }
                });
            }
            countDownLatch.await();
        }catch(Exception e){

        }finally {
            executor.shutdown();
        }
        System.out.println("完成了.");
    }

 

控制台打印结果

 

模板也看不懂的,实际上tkmybatis自带一种多线程的mapper接口

1.需要在你的mapper接口上继承,InsertListMapper

public interface InterviewProblemMapper extends Mapper<InterviewProblem>, InsertListMapper<InterviewProblem>, BaseMapper<InterviewProblem> {
}

2.调用即可

interviewProblemMapper.insertList(interviewProblems);

不过我觉得这种自带的不能够细粒度的控制,另外原生mybatis和mybatisPlus不确定是否有这种写好的接口,但手写多线程在多个orm框架上都适用.

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章