Back/Mybatis

대용량 데이터 조회 시 ResultHandler(RowHandler)

밍꿔 2020. 2. 19. 10:14


반응형

 

Mybatis를 사용하여 대용량데이터를 select해서 List<E> 형태로 호출 하게 되면 몇십만건 혹은

 

몇백만건 row data를 한번에 호출 하게 되면 OOM(Out of Memory)에러가 발생될 가능성이 매

 

우 높다.  보통, 엑셀 업로드, 다운로드 혹은 데이터 2차 가공 작업이 필요할때 위의 작업이 필요

 

한 경우가 발생 되는데, OOM오류를 회피하는 방법으로 Mybatis의 ResultHandler를 통해

 

데이터 Row별로 반복 작업이 가능하다. 아래의 소스를 통해 설명하자면,

 

// DI SqlSessionFactory 주입
@Autowired private SqlSessionFactory sqlSessionFactory;

---생략---

// 대용량 다운로드 시 ResultHandler를 사용한 Out of Memory 예외처리.
public List<VoTestInfo> getQAData(VoTestInfo voTestInfo){

	List<VoTestInfo> returnList = new ArrayList<>();

	try {

		SqlSession sqlSession = sqlSessionFactory.openSession();

		try {
			sqlSession.select("Text.getAllList", voTestInfo, new TestInnerResultHandler(returnList));
		} finally {
			sqlSession.close();
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return returnList;
}

 

sqlSession.select("Text.getAllList", voTestInfo, new TestInnerResultHandler(returnList)); 에서 


첫번째 인자값은 xml Namespace+쿼리ID
두번째 인자값은 파라미터
세번째 인자값은 InnerClass(실제로 로우별로 접근하여 값을 담는 클래스)

 

 

아래는 ResultHandler부분

 

import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;

import java.util.List;

public class TestInnerResultHandler implements ResultHandler {

    public List<VoTestInfo> returnList = null;

    public TestInnerResultHandler() {

    }
    public TestInnerResultHandler(List<VoTestInfo> returnList) {
        this.returnList = returnList;
    }

    @Override
    public void handleResult(ResultContext context) {
        Object object = context.getResultObject();
        returnList.add((VoTestInfo) object);
    }
}

 

ResultHandler를 implements한 클래스로 handleResult가 Override되고 실제 조회데이터를 Row별로 접근가능하다.

 

 

 

* 추가적인 내용으로

처음에는 TestInnerResultHandler를 해당 Service단에 내부클래스로 정의하여 개발했는데 로컬환경에서는 문제가 발생하지 않았지만 실제 Build해서 운영환경에 배포하고나니 내부클래스로 정의한 TestInnerResultHandler.class를 찾지 못하는 이슈가 발생.

(java.lang.NoClassDefFoundError - 컴파일 환경에서는 클래스 참조가 되었지만 실행 환경에서는 해당 클래스를 찾을수 없는 경우.)

이 때문에 따로 클래스를 정의함으로서 문제 해결.

 

* ibatis는 ResultHandler가 아니라 RowHandler를 사용해야함.

 

반응형