Java/Framework & Libs

Hibernate, fetch=FetchType.LAZY 선언된 필드에서 문제가 생길 경우

허니몬 2014. 1. 10. 18:24

문제발생지점

엔티티 클래스에 fetch=FetchType.LAZY로 선언해놓은 배열이나 객체를 사용하다 보면, 빈 배열로 선언되어 있는 경우,

Exception in thread "threadPoolTaskExecutor-5" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ...{collection}..., could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:266)
    ...{중략}...
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

위와 같은 예외가 발생한다.


처리방법

public final class Hibernate {
...
    /**
     * Force initialization of a proxy or persistent collection.
     * <p/>
     * Note: This only ensures intialization of a proxy object or collection;
     * it is not guaranteed that the elements INSIDE the collection will be initialized/materialized.
     *
     * @param proxy a persistable object, proxy, persistent collection or <tt>null</tt>
     * @throws HibernateException if we can't initialize the proxy at this time, eg. the <tt>Session</tt> was closed
     */
    public static void initialize(Object proxy) throws HibernateException {
        if ( proxy == null ) {
            return;
        }
        else if ( proxy instanceof HibernateProxy ) {
            ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().initialize();
        }
        else if ( proxy instanceof PersistentCollection ) {
            ( (PersistentCollection) proxy ).forceInitialization();
        }
    }
...
}

위에 설명한 Hibernate.initialize(대상 오브젝트나 컬렉션) 으로 lazy 컬렉션을 지정해주면 proxy 처리를 하면서 lazy 객체들을 미리 호출해놓는 것으로 보인다.