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框架上都適用.

 

 

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