다음과 같은 연관 관계를 갖는 entity를 정의했다.
Alpha (N : 1) Beta (1 : N) Gamma (N : 1) Delta
이때 Alpha
에서 부터 Delta
까지 탐색이 가능하게 양방향 연관 관계를 설정해두었다.
또한 모든 entity는 String name
이라는 속성을 갖게 정의했다.
Delta delta1 = new Delta("delta1");
Delta delta2 = new Delta("delta2");
Beta beta1 = new Beta("beta1");
Beta beta2 = new Beta("beta2");
Gamma gamma11 = new Gamma("gamma11", beta1, delta1);
Gamma gamma12 = new Gamma("gamma12", beta1, delta2);
Gamma gamma21 = new Gamma("gamma21", beta2, delta1);
Gamma gamma22 = new Gamma("gamma22", beta2, delta2);
Alpha alpha11 = new Alpha("alpha11", beta1);
Alpha alpha12 = new Alpha("alpha12", beta1);
Alpha alpha21 = new Alpha("alpha21", beta2);
Alpha alpha22 = new Alpha("alpha22", beta2);
Alpha |
Beta |
Gamma |
Delta |
---|---|---|---|
alpha11 | beta1 | gamma11 | delta1 |
alpha11 | beta1 | gamma12 | delta2 |
alpha12 | beta1 | gamma11 | delta1 |
alpha12 | beta1 | gamma12 | delta2 |
alpha21 | beta2 | gamma21 | delta1 |
alpha21 | beta2 | gamma22 | delta2 |
alpha22 | beta2 | gamma21 | delta1 |
alpha22 | beta2 | gamma22 | delta2 |
select distinct a from Alpha a join fetch a.beta b join fetch b.gammas g join fetch g.delta d
모두 join했기 때문에 쿼리는 한 번만 나간다.
결과는 다음과 같다.
alpha11 beta1 gamma11 delta1
alpha11 beta1 gamma12 delta2
alpha11 beta1 gamma11 delta1
alpha11 beta1 gamma12 delta2
alpha12 beta1 gamma11 delta1
alpha12 beta1 gamma12 delta2
alpha12 beta1 gamma11 delta1
alpha12 beta1 gamma12 delta2
alpha21 beta2 gamma21 delta1
alpha21 beta2 gamma22 delta2
alpha21 beta2 gamma21 delta1
alpha21 beta2 gamma22 delta2
alpha22 beta2 gamma21 delta1
alpha22 beta2 gamma22 delta2
alpha22 beta2 gamma21 delta1
alpha22 beta2 gamma22 delta2
결과를 보면 데이터가 중복되었다.
이는 Beta
와 Gamma
가 일대다 관계에 있기 때문이다. 일대다 조인의 경우 결과가 증가할 수 있다. 따라서 주의해야 한다.
이 방식을 사용하면 pagination을 사용하지 않는 것이 좋다. JPA에서는 지금과 같은 쿼리에 pagination을 할 경우 1. 쿼리의 결과를 모두 메모리에 올려서 2. 메모리에서 pagination을 한다. 여기서 쿼리의 결과는 중복된 데이터도 포함하기 때문에 OutOfMemory가 발생할 수 있다.
hibernate.default_batch_fetch_size=2
lazy loading을 할 때 한 번에 몇 개의 entity를 가져올 것인지에 대한 설정이다.