하이버네이트 매핑설정에는 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");
+ " 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());
'Framework' 카테고리의 다른 글
[AspectJ] aspect 재사용 방법 (0) | 2012.04.29 |
---|---|
[AspectJ] @within() 과 @annotation() 차이점 (0) | 2012.04.26 |
iBatis Abator 이름 변경 - iBATOR (1) | 2008.07.07 |
링크 : 어노테이션 기반 validation (0) | 2008.04.12 |
하이버네이트 늦은로딩은 영속상태에서만 가능하다. (2) | 2008.04.07 |