16. 양방향 연관관계와 연관관계의 주인1 - 기본

김성수·2023년 4월 6일
0

⚡ 생각대로 살지 않으면 사는대로 생각한다.

⚡ 나는 어차피 잘 될 놈이다. 이미 잘 되고 있고, 계속해서 잘 되고 있다.


양방향 매핑

테이블 연관관계는 앞에서 봤던 단방향 매핑에서 봤던 것과 바뀐 게 없이 똑같다.
테이블은 PK,FK를 맺어주면 방향이란 개념이 필요없다. 그냥 다 알 수 있다.

문제는... 객체..
Member에서 Team은 참조가능하지만, Team에서는 Member를 참조를 할 수 있는 방법이 없었다. Team에서 List members를 넣어줌으로 갈 수 있게 되었다.

단방향에서는 Member를 수정했는데, 양방향 매핑에서 Team쪽도 수정을 하면, Team에서 아래와 같이 코드를 작성해주면 된다.

@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();

@OneToMany(mappedBy = "team") : Member 클래스에서 변수 team으로 선언된 컬럼과 매핑하겠다.

Member 참고.

@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;

그리고

private List<Member> members = new ArrayList<>();

이와 같은 코드에서 members에 new ArrayList<>();로 초기화 해주는 것은 관례라고 한다. 그렇게 해야 add할 때 nullpointException 이 뜨지 않기 때문이다.

양방향 연관관계를 맺어주면 아래와 같이 코드 작성이 가능하다.

Member findMember = em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();

객체는 가급적이면 단방향이 좋다. 양방향 매핑을 하게되면 신경 쓸 것이 많다..

연관관계의 주인과 mappedBy

위의 @OneToMany(mappedBy = "team")에서의 mappedBy

  • mappedBy = JPA의 멘탈붕괴 난이도
  • mappedBy는 처음에는 이해하기 어렵다
  • 객체와 테이블간에 연관관계를 맺는 차이를 이해해야 한다.

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

Team과 Member를 가정

  • 객체 연관관계는 2개
    • Member -> Team 연관관계 1개(단방향)
    • Team -> Member 연관관계 1개(단방향)

단방향 연관관계가 사실 두 개가 있는 것.

  • 테이블 연관관계 1개
    • Member <-> Team 연관관계 1개(양방향)

테이블은 FK 하나로 테이블의 연관관계가 끝난다. 하지만, 객체는 참조가 서로에게 있어야 한다(단방향 두개)

객체의 양방향 관계

  • 객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개다.

  • 객체를 양방향으로 참조하려면 아래와 같이 단방향 연관관계를 2개 만들어야 한다.

A -> B (a.getB())

class A {
	B b;
}

B -> A (b.getA())

class B {
	A a;
}

테이블의 양방향 연관관계

  • 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리
  • MEMBER.TEAM_ID 외래 키 하나로 양방향 연관관계 가짐(양쪽으로 조인할 수 있다.)
SELECT * 
FROM MEMBER M
JOIN TEAM T ON T.TEAM_ID = T.TEAM_ID
SELECT * 
FROM TEAM T
JOIN MEMBER M ON T.TEAM_ID = M.TEAM_ID

문제는...

테이블의 FK로 가지고 있는 TEAM_ID(FK)를 update하려면, Member 객체가 가지고있는 Team team을 통해서 update해야하는지, Team 객체가 가지고있는 List membersupdate해야하는지 헷갈린다.

따라서 둘 중 하나로 외래 키를 관리해야하는데, 이 외래키를 관리하는 객체연관관계의 주인(Owner)이라고 한다.

연관관계의 주인(Owner)

양방향 매핑 규칙

  • 객체의 두 관계중 하나를 연관관계의 주인(Owner)으로 지정
  • 연관관계의 주인(Owner)만이 외래 키를 관리(등록, 수정)
  • 주인(Owner)이 아닌 쪽은 읽기만 가능
  • 주인(Owner)은 mappedBy 속성 사용 X
  • 주인(Owner)이 아니면 mappedBy 속성으로 주인(Owner) 지정
@Entity
public class Member {

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

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

이 두 객체에선 Member가 연관관계의 주인(Owner)이다.
mappedBy가 적힌 곳은 등록,수정이 불가능하고, 읽기(조회)만 가능하다.

누구를 주인으로?

  • 외래 키가 있는 곳을 주인으로 정하면 된다!

영한좌무수한 프로젝트를 깔끔하게 뽑아낸 기준... 설계, 성능이 깔끔해진다.

  • DB입장에서 외래 키가 있는 곳무조건 다(N)이다.
    • 외래 키가 없는 곳무조건 일(1)이다.
    • DB에서의 (N)다, 외래 키쪽이 연관관계의 주인이 되는 것이고, @ManyToOne이다.
  • 아래에서는 Member.team연관관계의 주인


아웅 재밌다.
-끝-

profile
쌩수 Git >> https://github.com/SsangSoo?tab=repositories

0개의 댓글