Mybatis 빅 데이터 양의 대량 insert 문 제 를 해결 합 니 다.
Mybatis 를 통 해 7000+데 이 터 를 대량으로 삽입 할 때 오류 가 발생 했 습 니 다.error log 는 다음 과 같 습 니 다.
,
('G61010352',
'610103199208291214',
' 52',
'G61010350',
'610103199109920192',
' 50',
'07',
'01',
'0104',
' ',
,
' ',
' ',
current_timestamp,
current_timestamp
)
중단 되 었 습 니 다.원인 을 얻 기 위해 getNextException 을 호출 하 십시오.
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2743)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:411)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2892)
at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:2596)
at com.alibaba.druid.wall.WallFilter.statement_executeBatch(WallFilter.java:473)
at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:2594)
at com.alibaba.druid.filter.FilterAdapter.statement_executeBatch(FilterAdapter.java:2474)
at com.alibaba.druid.filter.FilterEventAdapter.statement_executeBatch(FilterEventAdapter.java:279)
at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:2594)
at com.alibaba.druid.proxy.jdbc.StatementProxyImpl.executeBatch(StatementProxyImpl.java:192)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeBatch(DruidPooledPreparedStatement.java:559)
at org.apache.ibatis.executor.BatchExecutor.doFlushStatements(BatchExecutor.java:108)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:127)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:120)
at org.apache.ibatis.executor.BaseExecutor.commit(BaseExecutor.java:235)
at org.apache.ibatis.executor.CachingExecutor.commit(CachingExecutor.java:112)
at org.apache.ibatis.session.defaults.DefaultSqlSession.commit(DefaultSqlSession.java:196)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:390)
... 39 more
이러한 이상 은 포착 할 수 없습니다.druid 와 ibatis 의 원본 코드 만 이상 하 게 가리 키 는 것 을 볼 수 있 습 니 다.기본 적 인 SqlSession 이 이 수량 급 의 대량 작업 을 지원 하지 못 하기 때 문 이 라 고 초보 적 으로 추측 합 니 다.다음은 원본 코드 와 공식 문 서 를 결합 하여 구체 적 으로 보 겠 습 니 다.소스 코드 분석
프로젝트 는 Spring+Mybatis 를 사용 합 니 다.Dao 층 에 서 는 Spring 에서 제공 하 는 SqlSession Template 를 통 해 SqlSession 을 가 져 옵 니 다.
@Resource(name = "sqlSessionTemplate")
private SqlSessionTemplate sqlSessionTemplate;
public SqlSessionTemplate getSqlSessionTemplate()
{
return sqlSessionTemplate;
}
검증 을 위해 SqlSesion 을 어떻게 제공 하 는 지,SqlSession Template 의 소스 코드 를 열 고 구조 방법 을 살 펴 보 세 요.
/**
* Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
* provided as an argument.
*
* @param sqlSessionFactory
*/
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
}
다음 에 getDefaultExecutor Type 을 누 르 십시오.
public ExecutorType getDefaultExecutorType() {
return defaultExecutorType;
}
클래스 의 전역 변 수 를 직접 되 돌려 주 는 defaultExecutor Type 을 볼 수 있 습 니 다.클래스 의 머리 에서 이 변 수 를 찾 아 보 겠 습 니 다.
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
찾 았 습 니 다.Spring 이 제공 하 는 기본 실행 기 유형 은 Simple 입 니 다.그 유형 은 모두 세 가지 가 있 습 니 다.
/**
* @author Clinton Begin
*/
public enum ExecutorType {
SIMPLE, REUSE, BATCH
}
자세히 살 펴 보 니 세 개의 매 거 진 유형 이 있 는데 그 중 하 나 는 BATCH 가 대량 작업 과 관련 이 있 습 니까?my batis 공식 문서 에서 이 세 가지 값 에 대한 설명 을 살 펴 보 겠 습 니 다.-4
ExecutorType.SIMPLE
:이 실행 기 유형 은 특별한 일 을 하지 않 습 니 다.모든 문장의 실행 을 위해 새로운 예비 처리 문 구 를 만 듭 니 다.-4
ExecutorType.REUSE
:이 실행 기 유형 은 예비 처리 문 구 를 재 활용 합 니 다.-4
ExecutorType.BATCH
:이 실행 기 는 모든 업데이트 문 구 를 대량으로 실행 합 니 다.만약 에 SELECT 가 그들 사이 에서 실행 하면 그들 이 필요 하 다 고 표시 하여 간단 하고 이해 하기 쉬 운 행 위 를 보장 합 니 다.제 가 사용 하 는 SIMPLE 는 모든 문 구 를 위해 새로운 예비 처리 문 구 를 만 들 것 입 니 다.즉,Prepared Statement 대상 을 만 드 는 것 입 니 다.druid 연결 풀 을 사용 하여 처리 하 더 라 도 매번 풀 에 put 하고 druid 의 cache 에 가입 합 니 다.이 효율 은 짐작 할 수 있 기 때문에 그 이상 은 insert timeout 으로 인해 대기 시간 이 데이터베이스 구동 의 최대 대기 치 를 초과 할 수도 있 습 니 다.
자,이미 해 결 된 문 제 를 위주 로 하고 분석 에 따라 저 희 는 BATCH 방식 으로 SqlSession 을 만 들 고 정부 에서 도 일련의 과부하 방법 을 제공 합 니 다.
SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
주로 네 가지 매개 변수 유형 이 있 는데 그것 이 바로
- Connection connection
- ExecutorType execType
- TransactionIsolationLevel level
- boolean autoCommit
공식 문서 에서 이러한 매개 변수 에 대해 서도 상세 한 설명 이 있다.SqlSession Factory 는 SqlSession 인 스 턴 스 를 만 드 는 데 6 가지 방법 이 있 습 니 다.일반적으로 어떻게 결정 하 는 지 는 다음 과 같은 방법 을 선택 할 때 이다.
Transaction ( )
session 에 사 무 를 사용 하거나 자동 으로 제출 하고 싶 습 니까?4
Connection ( )
:MyBatis 가 설정 한 데이터 원본 의 연결 을 얻 고 싶 습 니까?아니면 자신 을 제공 하고 싶 습 니까?Execution ( )
MyBatis 는 예비 처리 문구 와/또는 일괄 업데이트 문 구 를 재 활용 하고 싶 습 니까?(삽입 과 삭제 포함)따라서 수요 에 따라 선택 하면 됩 니 다.우리 가 해 야 할 일 은 대량 insert 이기 때문에 SqlSession openSession(Executor Type exec Type,boolean autoCommit)을 선택 하 십시오.
참고 로 Transaction Isolation Level,즉 우리 가 자주 제기 하 는 사무 격 리 단계 에 대해 공식 문서 에서 도 잘 소개 되 었 습 니 다.
MyBatis 는 트 랜 잭 션 격 리 단계 에서 자바 매 거 진 포장 기 를 사용 합 니 다.Transaction IsolationLevel 이 라 고 합 니 다.그렇지 않 으 면 예상 한 방식 으로 작업 하고 JDBC 가 지원 하 는 5 단계 가 있 습 니 다.
NONE,
READ_UNCOMMITTED
READ_COMMITTED,
REPEATABLE_READ,
SERIALIZA BLE)
문 제 를 해결 하 다본론 으로 돌아 가 문제 의 원인 을 초보 적 으로 찾 았 습 니 다.SqlSession 의 획득 방식 을 바 꾸 어 다시 시도 해 보 겠 습 니 다.
testing… 2minutes later…
불 행 히 도 똑 같은 오 류 를 보고 하 는 것 은 Executor Type 의 문제 만 이 아 닌 것 같 습 니 다.commt 의 데이터 양 이 너무 많아 서 응답 시간 이 너무 긴 것 은 아 닐 까요?위 에서 저도 이런 가능성 을 언급 했 습 니 다.그러면 다시 한 번 일괄 처리 해 보 겠 습 니 다.즉,같은 업무 범위 내 에서 commt insert batch 를 나 누 어 보 겠 습 니 다.Dao 층 의 코드 구현 을 구체 적 으로 살 펴 보 겠 습 니 다.
@Override
public boolean insertCrossEvaluation(List<CrossEvaluation> members)
throws Exception {
// TODO Auto-generated method stub
int result = 1;
SqlSession batchSqlSession = null;
try {
batchSqlSession = this.getSqlSessionTemplate()
.getSqlSessionFactory()
.openSession(ExecutorType.BATCH, false);// sqlsession
int batchCount = 1000;// commit
int batchLastIndex = batchCount;//
for (int index = 0; index < members.size();) {
if (batchLastIndex >= members.size()) {
batchLastIndex = members.size();
result = result * batchSqlSession.insert("MutualEvaluationMapper.insertCrossEvaluation",members.subList(index, batchLastIndex));
batchSqlSession.commit();
System.out.println("index:" + index+ " batchLastIndex:" + batchLastIndex);
break;// ,
} else {
result = result * batchSqlSession.insert("MutualEvaluationMapper.insertCrossEvaluation",members.subList(index, batchLastIndex));
batchSqlSession.commit();
System.out.println("index:" + index+ " batchLastIndex:" + batchLastIndex);
index = batchLastIndex;//
batchLastIndex = index + (batchCount - 1);
}
}
batchSqlSession.commit();
}
finally {
batchSqlSession.close();
}
return Tools.getBoolean(result);
}
재 테스트,프로그램 에 이상 이 없습니다.총 7728 개의 데이터 insert 시간 은 약 10s 정도 입 니 다.아래 그림 과 같 습 니 다.총결산
Mybatis 대량 insert 빅 데이터 양 데 이 터 를 간단하게 기록 하 는 솔 루 션 입 니 다.참고 로 Tne End.
추가:my batis 대량 삽입 오류:','근처에 오류 가 있 습 니 다.
my batis 대량 삽입 시 오류,오류 메시지','근처에 오류 가 있 습 니 다.
mapper.xml 의 작성 방법 은?
<insert id="insertByBatch">
INSERT INTO USER_LOG (USER_ID, OP_TYPE, CONTENT, IP, OP_ID, OP_TIME) VALUES
<foreach collection="userIds" item="userId" open="(" close=")" separator=",">
(#{rateId}, #{opType}, #{content}, #{ipStr}, #{userId}, #{opTime},
</foreach>
</insert>
인쇄 된 sql 문장
INSERT INTO USER_LOG (USER_ID, OP_TYPE, CONTENT, IP, OP_ID, OP_TIME) VALUES (
(?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?) )
디 버 깅 할 때 도 sql 을 navicate 에 복사 하여 검 사 를 하 였 는데,위의 잘못 을 보고 하 였 다.이 잘못 은 갈 피 를 잡 을 수 없 는 것 처럼 보 였 고,그 다음 에 스스로 insert 문 구 를 다시 썼 는데,정확 한 문 구 는
INSERT INTO USER_LOG (USER_ID, OP_TYPE, CONTENT, IP, OP_ID, OP_TIME) VALUES (?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?)
이전 sql 보다 괄호 가 적 습 니 다.이 때 실행 에 성 공 했 기 때문에 mapper.xml 에 서 는 opern=(close=)을 삭제 하면 됩 니 다.한 마디 만 더 하면 대량으로 삽입 할 때 삽입 할 데 이 터 를 List<실체>로 조립 할 수 있 습 니 다.이렇게 많은 인 자 를 전달 하지 않 아 도 됩 니 다.
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
SpringMVC와 Mybatis 집합은 호출 저장 프로세스, 사무 제어 실례를 실현한다SSM 프레임워크에서 호출 데이터베이스의 저장 프로세스와 사무 제어에 자주 사용되는데 다음은 증빙서류를 저장하는 예를 들어 소개한다. 1. Oracle에 저장된 프로세스 코드는 다음과 같습니다(주요 논리는 증빙 서류...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.