특정 엔티티의 갯수가 많고, 그것을 한번에 처리하려고 하는 경우에 Query 나 Criteria 를 이용해 .list() 를 할 경우에, OutOfMemoryError(OOME) 가 나기 쉽상이다.

BadExample.java
Query q = getSession().createQuery("FROM "+Contents.class.getName())
                    .setReadOnly(true);
List<Contents> contentsList = q.list();
for (Contents contents : contentsList) {
    // TODO work here
};

이것을 처리하기 위해서는 scroll 을 이용하여 특정 데이터씩만 조회하여 처리한 후, 세션을 클리어해주면 된다.

GoodExample.java
ScrollableResults results = getSession().createQuery("FROM "+Contents.class.getName())
    .setReadOnly(true).setCacheable(false)
    .setCacheMode(CacheMode.IGNORE)
    .setFetchSize(10)
    .scroll(ScrollMode.FORWARD_ONLY);
while (results.next()) {
    Contents contents = (Contents)results.get()[0];
    // TODO work here  
    getSession().clear();
}

중요한 부분은 다음 포인트다.

  • list 대신 Cursor 를 이용하는 scroll 메서드를 이용한다.
  • Fetch 사이즈를 적절히 설정해서 한번에 처리할 레코드 수를 설정한다.
  • 작업 처리 후에는 Session 을 clear 한다.

이렇게 하면 메모리 부족 현상에서 해결된다.

하이버네이트를 혐오하는 사람들 중의 생각 하나가, "메모리에 다 올려놓으니깐 못 써먹는다" 인데 그럴리가 있니?

+ Recent posts