이번엔 JPA의 양방향 매핑에 대해 알아보자
저번 글에서 Member에서 Team을 조회하는 경우 N:1로 단방향으로 매핑 시켰다고 했다.
만약, Team 객체 에서 해당하는 Team에 소속된 Member들을 모두 조회해야하는 경우에 Team 객체 에서도 연관관계를 걸어줘야 한다. 이때의 연관관계를 양방향 연관관계라고 한다.
N:1 양방향 관계를 이해하기 위해 Member와 Team의 관계를 살펴보자.
해당 관계를 보면 기존의 N:1 단방향 관계와 다를 것이 없다.
왜냐하면 데이터베이스는 방향 이라는 것이 없기 때문이다
그저 외래키를 사용하여 두 테이블을 Join 시켜 내가 원하는 테이블의 데이터를 조회할 수 있다.
해당 사실을 바탕으로 다시 우리가 원하는 것을 생각해보면 총 두 가지이다.
1. 회원(Member) 객체에서 팀(Team)객체를 조회할 수 있어야 한다.
2. 팀(Team) 객체에서 회원(Member)객체 목록을 조회할 수 있어야 한다.
이것을 모델링한 객체 와 테이블 결과는 아래와 같다.
이에 맞게 Member 객체와 Team 객체를 만들어보자.
위의 회원(Member) 클래스의 코드는 단방향 매핑때와 일치하다.
위의 코드는 Team 엔티티에 members라는 필드가 추가되었다.
단뱡향 매핑과는 다르게 @OneToMany 어노테이션을 추가하여 연관관계를 걸어주었다.
@OneToMany 어노테이션의 mappedBy 속성은 양방향 매핑일 때 사용하며, 반대쪽 매핑의 필드 이름값으로 설정한다. 이것은 연관관계의 주인을 설정하기 위한 것이다.
여기서 의문점이 하나 생긴다.
어떤건 @JoinColumn 쓰고, 어떤건 안쓰고 뭐지?
또, Member에서는 @JoinColumn을 걸어줬는데 Team에서는 안쓰네?
이것을 이해하기 위해 먼저, 객체와 테이블이 관계를 맺는 차이를 살펴보자.
양방향 연관관계 시 객체와 테이블은 다르다!
테이블은 외래키(FK)로 다른 테이블과 Join 시키면 다른 테이블의 정보도 알 수 있다. 그러므로 연관관계를 1개만 걸어주면 된다.
하지만 객체의 연관관계에서는 각각의 객체마다 참조를 걸어줘야 하므로 총 2개의 연관관계를 걸어줘야 한다. 이것을 우리는 양방향 연관관계라고 부른다.
여기서 나는 두 객체에서 어떤 것으로 매핑을 해야하지?라는 의문이 생긴다.
아래의 객체 연관관계를 보자.
상황을 가정해보자.
한 회원(Member)의 팀을 바꿔야 한다.
팀을 바꾸면 그림의 아래에 있는 Member 테이블의 외래키인 TEAM_ID를 업데이트 해야한다.
이 업데이트 작업을 Member 객체의 team으로 해야되는가?
아니면 TEAM 객체의 members 로 해야되는가?
단뱡향 이었을때는 당연히 회원(Member)객체에서 팀(Team)을 참조하므로 이 팀(Team)만 연관관계 매핑을 하면 되지만,
양방향인 경우에는 팀(Team) 객체의 members도 신경을 써야 하므로 어떻게 해야할지 난감하다.
결론은 둘 중 하나로 주인을 정해서 외래 키를 관리해야 한다는 것이다. 이것이 연관관계의 주인이다.
우리의 예시인 회원(Member)와 팀(Team)의 경우에는 외래키가 있는 곳인 회원이 주인이다.
팀(Team) 객체에서 @OneToMany 어노테이션의 mappedBy 속성으로 회원(Member) 객체의 team 필드와 연관관계를 정의해 주었다.