특정 엔티티의 갯수가 많고, 그것을 한번에 처리하려고 하는 경우에 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 한다.
이렇게 하면 메모리 부족 현상에서 해결된다.
하이버네이트를 혐오하는 사람들 중의 생각 하나가, "메모리에 다 올려놓으니깐 못 써먹는다" 인데 그럴리가 있니?