배치의에서 MyBatis로 삽입 많은 양의 데이터를
시나리오 : 가져 오기 엑셀 표는 데이터를 읽은 다음 일괄 데이터베이스에 삽입
등 다음 서비스의 키 코드입니다.
목록 컬렉션에서 직접 데이터를 삽입 패스
bindCardInsertLogMapper.batchInsertHzjjBindCodeLog(list);
XML
<insert id="batchInsertHzjjBindCodeLog">
INSERT INTO hzjj_batch_bind_code_log (id_card,yt_no,redeem_code,card_no,password,name,batch_id,ip,course_id) VALUES
<foreach collection="list" item="log" separator=",">
(#{log.idCard},#{log.ytNo},#{log.redeemCode},#{log.cardNo},#{log.password},#{log.name},#{log.batchId},#{log.ip},#{log.courseId})
</foreach>
</insert>
처음에는 인터페이스를 호출하는 데 문제가 없었고 모든 것이 정상이었습니다. 나중에 한 번에 300 개의 데이터를 가져올 때 오류가 직접보고되었습니다 :
들어오는 TDS (Tabular Data Stream) 원격 프로 시저 호출 (RPC) 프로토콜 흐름 잘못되었습니다. 이 RPC 요청에 너무 많은 매개 변수가 제공되었습니다.
Mybatis가 SQL SERVER를 호출 할 때 삽입 또는 쿼리 수정 및 기타 작업에 관계없이 매개 변수가 제한 ** 되어 있는지 확인하기 위해 데이터 를 확인하려면 최대 2100이어야합니다 . 매개 변수 길이가 2100을 초과하면이 오류가보고됩니다. **
솔루션 :
여러 스레드가 일괄 적으로 데이터를 삽입하고 원래 1000 개의 데이터를 삽입하고 10 개의 스레드를 시작하고 스레드 당 100 개를 삽입하는 것은 괜찮습니다.
다음과 같이 코드를 해결 한 후 :
//因为我这边数据不会很多,所以线程池就直接使用CachedThreadPool,没有自定义一个线程池。
ExecutorService executorService = Executors.newCachedThreadPool();
//num 数据被分为多少批可以发送完
//100 每个线程批量插入100个
int num=list.size()/100;
if(list.size()%100>=0){
num=num+1;
}
// lastIndex 截取结束坐标
int lastIndex=0;
for (int i=0;i<num;i++){
if(100*(i+1)>list.size()){
lastIndex=list.size();
}else{
lastIndex= 100*(i+1);
}
//多线程批量添加
executorService.submit(new BatchInsertHzjjCodeThread(list.subList(i*100,lastIndex),bindCardInsertLogMapper));
}
//关闭线程池,拒绝接收任务
executorService.shutdown();
while (true){
//任务是否结束 进行下一步操作
if(executorService.isTerminated()){
bindCardInsertLogMapper.batchBindHzjjCode(batchId);
break;
}
}
그런 다음 테이블을 다시 가져 오면 정상적으로 추가 할 수 있습니다.