[iBatis] queryWithRowHandler 메소드를 사용한 RowHandler사용하기
iBatis는 DB쿼리문의 결과를 Java Object로 매핑시켜주는 Persistent Layer의 Framework로서 DB쿼리로 검색된 결과를 다양한 자바 오브젝트( Custom Object, List, Map 등)로 생성, 매핑 시켜주어 DB 쿼리 결과를 자바단에서 쉽게 사용할수 있도록 해줍니다.
그러나 수행한 쿼리의 Row수가 대량일 경우 iBatis는 문제를 일으키게 됩니다.
예를 들어 특정 쿼리로 검색된 row의 수가 천만건이 된다고 하면, iBatis는 해당 쿼리 결과를 자바 오브젝트에 매핑 시키기 위해 사이즈가 천만인 ArrayList 인스턴스를 생성하게 될것입니다. 그렇게 대량의 자바 인스턴스를 생성하게 되면 JVM에서 사용하는 메모리사이즈를 초과하게 되어 결국 Out of Memory Exception를 뿜으며 시스템이 뻗어버리게 됩니다.
위와 같이 대량의 데이터를 셀렉트 해오는 경우에는 RowHandler를 사용하여 Out Of Memory Exception을 피해갈수 있습니다.
RowHandler를 생성하는 방법은 com.ibatis.sqlmap.client.event.RowHandler 인터페이스를 impliments 하면 됩니다.
public class TestRowHandlerCallback implements RowHandler { @Override public void handleRow(Object arg0) { TestClass class = (TestClass) arg0; //TODO select된 row 하나하나가 Java Object로 생성되어 넘어온다. } }
이렇게 만들어진 RowHandler는 SqlMapClient를 사용할때 queryWithRowHandler라는 메소드를 사용하여 RowHandler를 사용하도록 지정하면 됩니다.
TestRowHandlerCallback callback = new TestRowHandlerCallback(); //getSqlMapClientTemplate().queryWithRowHandler("Test.rowHandlerTestQuery", callback); //스프링 사용시 getSqlMapClient().queryWithRowHandler("Test.rowHandlerTestQuery", callback);
이렇게 queryWithRowHandler 메소드로 RowHandler를 지정하게 되면 iBatis는 List 인스턴스를 생성하지 않고 Row당 하나의 자바 오브젝트를 생성한 후 RowHandler의 handleRow 메소드를 실행시킵니다.
이렇게 되면 아무리 많은 row가 검색되었다고 하더라도 List Object를 생성하지 않기 때문에 Out Of Memory Exception이 발생하지 않게 되어 안전하게 개발할 수 있습니다.