하이버네이트 매핑설정에는 lazy 옵션이 있습니다. 연관객체를 언제 로딩할거냐에 대한 옵션입니다. true로 설정하면 하이버네이트는 부모객체를 로딩할 때 그에 딸린 연관객체(자식객체)를 미리 로딩하지 않고 프록시 객체만 만들어둡니다. 그리고는 실제로 연관객체가 사용될 때 연관객체를 로딩하죠. false이면 부모객체가 로딩될 때 연관객체도 함께 미리 로딩합니다.

Employee(부모)와 Achievement(자식) 가 있습니다. 아래처럼 lazy=true 로 설정되어 있기 때문에 Achievement 목록은 실제 쓰이지 않는다면 로딩되지 않습니다.

<class name="Employee" table="EMP">
... ...
<set name="achievements"

       lazy="true" 

      ... ... >

    <key column="EMP_ID" />
    <one-to-many class="Achievement" />
</set>

그러나 연관객체를 미리 로딩하고 싶을 때도 있습니다. 크게 세가지 방법이 있습니다.

 (1) HQL fetch 키워드 사용
left outer join fetch 키워드를 사용하면 lazy=true, fetch=select 이더라도
조인을 통해 1번의 쿼리로 연관객체를 모두 가져옴.
 
Query q = session.createQuery(" from Employee as emp "
        + " left outer join fetch emp.achievements "
        + " where emp.id = :employeeId");

q.setParameter("employeeId", employeeId);
employee = (Employee) q.list().get(0);
 
(2) Criteria에서 fecth mode를 JOIN으로 설정
 
Criteria c = session.createCriteria(Employee.class);
c.setFetchMode("achievements", FetchMode.JOIN);
c.add(Restrictions.idEq(employeeId));
employee = (Employee) c.uniqueResult();
 
(3) Hibernate.initialize 메소드 이용
연관객체를 임의로 미리 로딩. 단, 세션안에서만 사용가능.
 
employee = (Employee) session.get(Employee.class, employeeId);
Hibernate.initialize(employee.getAchievements());

Posted by 에코지오
,