본문 바로가기
강의 정리/자바 ORM 표준 JPA

4. 연관관계 매핑 기초

by 이석준석이 2020. 12. 27.

패러다임의 불일치

  • 테이블은 외래키로 조인을 사용해서 연관된 테이블을 찾는다.
  • 객체는 참조를 사용해서 연관된 객체를 찾는다.

1. 양방향 연관관계

단방향 양방향

패러다임의 불일치

  • 테이블은, Foreign Key 한개만 있으면 양쪽으로 모두 조회가 가능하다.
  • 객체는 양쪽에 모두 세팅해줘야 양쪽으로 모두 조회가 가능하다.

2. 연관관계 주인과 mappedBy

 

객체와 테이블이 관계를 맺는 차이

 

객체 = 연관관계 2개 = 단방향 연관관계 2개

  • 회원 -> 팀 연관관계 1개 (단방향)
  • 팀 -> 회원 연관관계 1개 (단방향)

 

테이블 = 연관관계 1개

  • 회원 <-> 팀 연관관계 1개만으로, (양방향)을 모두 접근할 수 있음
객체의 양방향 관계는 사실, 서로 다른 단방향 관계 2개이다. 테이블은 하나의 외래키로, 양방향 연관관계를 할 수 있다.

 

연관관계의 주인 (Owner)

연관관계의 주인은 어떻게정할까? (1, 2번의 조건이 있다면)

1. Member 내부에 Team 값이 없고, Team 내부에 members에 Member 가 속해있다면, 그때 데이터베이스에 있는 TEAM_ID 를 갱신해야하는가?

2. Member 내부에 Team 값이 있고, Team 내부에 members에 Member가 속해있지 않다면, 그때 데이터베이스에 있는 TEAM_ID 를 갱신해야하는가?

헷갈린다.. 따라서 이 생긴다.
- 둘 중 하나로 외래키를 관리해야한다.
     - 아니면 List members (1번) 로 관리할 것이냐
     - team 으로 관리 (2번)할 것이냐,

따라서, 위의 룰을 기초로

  • Member 내부에 있는 team
  • Team 내부에 있는 members

중, 어떤 거에 따라서 데이터베이스에 있는 Team_ID(FK) 를 갱신할 것인지 선택해야 한다.

 

선택이 완료됐다면

  • 연관관계의 주인만이 외래키를 등록, 수정, 조회 할 수 있다.
  • 주인이 아닌 쪽은 읽기만 가능하다.
  • 주인 쪽에는 mappedBy가 없다.
  • 주인이 아닌쪽에서 mappedBy 속성을 통해 주인을 지정한다.

그렇다면 선택은 누구로 해야하는가???

  • 위의 그림에 기반하면, Member.team 혹은 Team.members 둘 중 누구를 선택해야하는가?
  • 외래키가 있는 곳을 주인으로 정해라 (절대적인 것은 아니나 이게 맞다.)

이유는?

  • 만약 외래키가 없는 쪽인 Team.members를 주인으로 했다고 해보자.
    • Team.members.add(member) 를 하면 Member Table의 FK 가 갱신된다.
    • Team.members.remove(member) 를 하면 Member Table 의 FK 가 갱신된다.
  • Team 쪽에서 추가를 했는데 Member Table 의 FK 가 변한다?
    • 벌써부터 복잡해진다.
    • 또한, 성능이슈도 있다.

 

  • 반대로 한다면, Member.Team 을 주인으로 했다면
    • Member.add(team) 을 하면 Member Table의 FK 가 갱신된다.
    • Member.remove(team) 을 하면 Member Table 의 FK 가 갱신된다.
  • Member 쪽에서 변경을 가했고, Member Table 의 FK 가 변하므로
    • 이해가기가 좋다.

3. 양방향 연관관계 주의점

 

1. 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자.

  • Member.team 을 연관관계의 주인으로 설정했으므로
    • Member.setTeam(team) 만 해도, 데이터베이스의 FK 에는 트랜잭션이 커밋된 이후 정상적으로 반영되나
    • 객체지향적인 관점에서 team.getMembers.add(member) 를 같이 해주자.
    • 자세한 이유는 실제 강의를 참조!

2. 연관관계 편의 메소드를 생성하자

public void changeTeam(Team team) {
    this.team = team;
    team.getMembers().add(this);
}

3. 양방향 관계에서 무한루프를 조심하자

  • toString()
  • Json 생성 라이브러리
    • 엔터티를 직접 Response로 보내버리는 경우에 생긴다.
    • 해결책 : 컨트롤러에서는 엔터티를 절대 반환하지 말아라, Dto로 변환해서 반환해라

4. 팁

 

단방향 매핑만으로 설계를 끝내라

  • 나중에 필요하면 추가하면된다.
  • 어차피 데이터베이스 테이블에는 영향 안준다.

'강의 정리 > 자바 ORM 표준 JPA' 카테고리의 다른 글

6. 고급 매핑  (0) 2020.12.29
5. 다양한 연관관계 매핑  (0) 2020.12.28
3. 엔티티 매핑  (0) 2020.12.27
2. 영속성 관리  (0) 2020.12.26
1. JPA 시작하기  (0) 2020.12.26