하이버네이트 매핑설정에는 lazy 옵션이 있습니다. 연관객체를 언제 로딩할거냐에 대한 옵션입니다. true로 설정하면 하이버네이트는 부모객체를 로딩할 때 그에 딸린 연관객체(자식객체)를 미리 로딩하지 않고 프록시 객체만 만들어둡니다. 그리고는 실제로 연관객체가 사용될 때 연관객체를 로딩하죠. false이면 부모객체가 로딩될 때 연관객체도 함께 미리 로딩합니다.
Employee(부모)와 Achievement(자식) 가 있습니다. 아래처럼 lazy=true 로 설정되어 있기 때문에 Achievement 목록은 실제 쓰이지 않는다면 로딩되지 않습니다.
그러나 연관객체를 미리 로딩하고 싶을 때도 있습니다. 크게 세가지 방법이 있습니다.
(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());