연관관계 매핑 기초 - 양방향 연관관계

정민기·2021년 8월 21일
0

Java ORM JPA

목록 보기
4/9

양방향 연관관계와 연관관계의 주인

양방향 매핑

  • 모델링
    아래 그림을 보면 객체에서 양방향으로 연관관계를 설정해도 테이블은 단방향과 차이점이 없다. 즉 테이블에서는 방향이라는 개념 없이 외래 키를 이용해서 조인하여 서로의 연관관계를 알 수 있다. 하지만 객체에서 Team이 Member를 참조하기 위해서는 Member의 list가 Team 객체 내에 존재해야 한다.

  • 양방향 연관관계 코드
    Member의 경우 단방향과 동일하다.

  @Entity
    public class Member {
    ...
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    ...
  }

Team에서는 List를 통해 Member를 참조하게 되고, 이때 mappedBy = "team"을 통해 Member 객체 내의 Team team과 매핑을 해줄 수 있다.

 @Entity
 public class Team {
   ...
   @OneToMany(mappedBy = "team")
   List<Member> members = new ArrayList<Member>();
   ...
 }

이를 통해 아래 코드와 같이 Team에서도 Member를 조회할 수 있다.

//조회
Team findTeam = em.find(Team.class, team.getId());
Member findMember = em.find(Member.class, member.getId());

//Team으로부터 Member정보 조회
int memberSize = findTeam.getMember().size();
//Member로부터 Team을 조회 후 Team에 속한 모든 Member조회
List<Member> members = findMember.getTeam().getMembers();

연관관계의 주인과 mappedBy

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

  • 객체 연관관계 = 2개

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

    • 회원 <-> 연관관계 (양방향)
  • 객체의 양방향 연관관계
    객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개이다. 즉 객체를 양방향을 참조하려면 단방향 연관관계를 2개 만들어야 한다.

  • 테이블의 양방향 연관관계
    테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다. 즉 양쪽으로 조인할 수 있다.

  • 외래 키 관리
    객체 관점에서는 2개의 단방향 연관관계가 존재하지만 테이블 상에서는 하나의 외래 키만 존재한다. 따라서 2개의 연관관계 중 하나가 이 외래 키를 관리해야 한다.

연관관계의 주인

  • 양방향 매핑 규칙
    • 객체의 두 관계 중 하나를 연관관계의 주인으로 지정
    • 연관관계의 주인만이 외래키를 관리(등록, 수정)
    • 주인이 아닌 쪽은 읽기만 가능
    • 주인은 mappedBy 속성 사용 X
    • 주인이 아니면 mappedBy 속성으로 주인 지정
  • 주인은 무엇으로?
    외래 키가 있는 곳을 주인으로 정한다. 아래 그림의 경우 Member 테이블에 외래 키가 존재하므로 Member 객체가 연관 관계의 주인이 된다.

    연관관계의 주인은 비지니스 적으로 중요한 것이 아닌 설계 상에서 유리한 곳을 주인으로 하는 것이 정석이다.

양방향 매핑 시 주의점

  • 연관관계의 주인에 값을 입력하지 않는 경우
    아래 코드와 같이 연관관계의 주인에 값을 입력하지 않을 경우 Member 테이블은 Team을 참조하지 못했으므로 null 값만 존재하게 된다.
  Team team = new Team();
  team.setName("TeamA");
  em.persist(team);

  Member member = new Member();
  member.setName("member1");

  //역방향(주인이 아닌 방향)만 연관관계 설정
  team.getMembers().add(member);

  em. persist(member);


따라서 반드시 주인에 값을 입력해야 하고, 순수한 객체 관계를 고려해서 항상 양쪽 모두 값을 입력해야 한다.

  ...
  //연관관계의 주인인 member에 값 설정
  member.setTeam(team);
  //team에도 연관관계 설정
  team.getMembers().add(member);
  ...

  • 연관관계 편의 메소드를 생성하자.
  • 양방향 매핑 시에 무한 루프를 조심하자.
    Ex) toString(), lombok(되도록이면 toString 쓰지 말자), JSON 생성 라이브러리(Controller에서 Entity를 반환하지 말자!, DTO로 변환하여 반환하자)

양방향 매핑 정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료 즉 JPA에서 객체와 테이블 설계는 단방향으로도 완료되어야 한다.
  • 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐이다.
  • JPQL에서 역방향으로 탐색할 일이 많다.
  • 따라서 단방향 매핑을 잘 해두면 양방향은 필요할 때 추가해도 된다. 이때 테이블에는 영향을 주지 않는다.
  • 연관관게의 주인은 외래 키의 위치를 기준으로 정해야 한다. 비지니스 로직을 기준으로 주인을 선택하면 안된다.



[Reference]

Inflearn 김영한 님의 자바 ORM 표준 JPA 프로그래밍 - 기본편 : https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

0개의 댓글

관련 채용 정보