티스토리 뷰

이전 포스팅에서 양방향 매핑에 대해 알아보았습니다. 단방향, 양방향 연관관계에 대해서 알아보았고 연관관계의 주인을 설정하는 것 까지 알아보았습니다 ! 이번에는 연관관계를 매핑하는 것에 대해 알아보겠습니다. 연관관계 매핑시 고려해야할 점이 3가지가 있습니다. 첫 번째는 '다중성', 두 번째는 '단방향, 양방향', 세 번째는 '연관관계의 주인' 입니다.

 

먼저 다중성은 1:1, 1:N과 같은 비율을 이야기합니다. JPA에서 다룰 수 있는 다중성은 N:1(@ManyToOne), 1:N(@OneToMany), 1:1(@OneToOne), N:M(@ManyToMany)가 있습니다. 이런 다중성과 함께 단방향, 양방향 매핑을 정할 수 있습니다. 테이블은 외래 키 하나로 양쪽 조인이 가능하고, 객체는 참조 필드가 있는 쪽으로만 참조가 가능하며 한쪽만 참조하면 단뱡항, 양쪽이 서로 참조하면 양방향 관계입니다. 객체 양방향 관계는 A->B, B->A 처럼 참조가 2군데 있는 것을 말하며, 연관관계의 주인은 외래 키를 가지고 있는 객체를 말합니다. 다양한 연관관계 매핑에 대해 좀 더 자세히 알아보겠습니다.

 

다대일(N:1)

- 다대일 단방향

가장 많이 사용하는 연관관계입니다. 다대일의 반대는 일대다입니다.

 

- 다대일 양방향

외래 키가 있는 쪽이 연관관계의 주인이고 여기서는 Member가 연관관계의 주인입니다. Team은 멤버 객체를 조회만 할 수 있습니다. 당연히 양쪽을 서로 참조하도록 개발해야 합니다.

 


일대다(1:N)

- 일대다 단방향

일대다 단방향은 1:N에서 1이 연관관계의 주인입니다. 즉 그림의 예제에서 Team이 연관관계의 주인입니다. 테이블의 일대다 관계는 항상 다(N) 쪽에 외래 키가 있기 때문에 Team객체가 반대편 테이블인 Member의 외래 키를 관리하는 특이한 구조를 가지게 됩니다. 반드시 @JoinColumn을 사용해야 하고 그렇지 않은면 중간에 테이블을 하나 추가하는 조인 테이블 방식을 사용하게 됩니다. 그러므로 N:1 모델에서 양방향 매핑을 추가하는 것을 고려해보는 것이 좋습니다. 결론적으로 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하는 것이 바람직할 것 같습니다 !!

 

일대다 양방향 매핑도 마찬가지 입니다. 공식적으로 존재하지 않는 매핑이며 다대일 양방향을 사용하는 것이 바람직합니다.

 


일대일(1:1)

일대일 관계는 그 반대의 관계도 일대일 입니다. 주 테이블이나 대상 테이블 중에 외래 키를 선택할 수 있습니다.

- 주 테이블에 외래 키 단방향

주 객체가 대상 객체의 참조를 가지는 것 처럼, 주 테이블에 외래 키를 두고 대상 테이블을 찾습니다. 다대일 단방향 매핑과 유사한 구조이고 JPA 매핑이 편리하며 주 테이블만 주회해도 해당 테이블에 데이터가 있는지 확인할 수 있습니다.

 

- 주 테이블에 외래키 양방향

다대일 양방향 매핑처럼 외래 키가 있는 곳이 연관관계의 주인입니다. 반대편은 mappedBy를 적용하면 됩니다.

 

 

- 대상 테이블에 외래 키 단방향

대상 테이블에 외래 키가 있고 단방향 매핑인 경우는 JPA가 지원하지 않습니다. 그러므로 양방향 매핑으로 변경해야 합니다.

 

- 대상 테이블에 외래 키 양방향

일대일 주 테이블에 외래 키가 있는 단방향 모델에서 양방향 매핑만 추가한 것과 같습니다. 그러나 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됩니다. 그러므로 실제 개발환경에서 사용하기에 다소 부적적한 모델이라고 생각됩니다(주관적인 생각입니다).

 


다대다(N:M)

관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없습니다. 그러므로 연결 테이블을 추가해서 일대다 - 다대일 관계로 풀어내야합니다. 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능합니다. @ManyToMany를 사용하며 @JoinTable로 연결 테이블을 지정합니다. 

연결 테이블용 엔티티를 추가하여 다대일 관계를 풀어낼 수 있습니다. 연결 테이블을 엔티티로 승격시키는 것입니다. @ManyToMany -> @OneToMany, @ManyToOne으로 풀어냅니다. 결론적으로 N:M 매핑을 사용하지 말고 1:N, N:1로 풀어서 사용하는 것이 좋겠습니다.

댓글