본문 바로가기

개발중/Java Persistence API (JPA)

JPA / 객체 간 연관관계 매핑 - 기록

728x90
반응형

JPA 책을 읽다가 기록하고 내 것으로 만들고 싶은 부분 기록


 DB Table 구성

 

CREATE TABLE MEMBER (
  MEMBER_ID VARCHAR(255) NOT NULL
  , TEAM_ID VARCHAR(255)
  , USERNAME VARCHAR(255)
  , PRIMARY KEY (MEMBER_ID)
)
;

CREATE TABLE TEAM (
  TEAM_ID VARCHAR(255) NOT NULL
  , NAME VARCHAR(255)
  , PRIMARY KEY (TEAM_ID)
)
;

ALTER TABLE MEMBER ADD CONSTRAINT FK_MEMBER_TEAM FOREIGN KEY (TEAM_ID) REFERENCES TEAM
;

 Class

- Member 

class Member {

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

---
}

 

- Team 

class Team {

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

---
}

 

연관관계의 주인을 정한다. 는 것은 외래 키 관리자를 선택하는 것이다.

여기서는 회원 테이블에 있는 TEAM_ID 외래 키를 관리할 관리자를 선택해야 한다,

 

여기서 Team.members 를 외래키를 관리할 관리자로 선택한다면 전혀 다른 테이블의 외래 키를 관리하기 때문에.

이 경우에는

Member.team 에서 외래키를 관리한다.

 

결국 연관관계의 주인만 DB 와 매핑 되고 외래키를 관리할 수 있다.

주인이 아닌 반대편은 읽기만 가능하고 외래키를 변경하지는 못한다.


 연관관계의 주인을 정하는 기준

단방향은 항상 외래 키가 있는 곳을 기준으로 매핑하면 된다.

하지만 양방향은 연관관계의 주인이라는 이름으로 인해 오해가 있을 수 있다.

 

비즈니스 로직상 더 중요하다고 연관관계의 주인으로 선택하면 안된다.

비즈니스 중요도를 배제하고 단순히 외래 키 관리자 정도의 의미만 부여해야 한다.

 

예를 들어 회원과 팀 엔티티는 외래 키가 있는 다 쪽인 회원인 연관관계의 주인이 된다.

물론 비지니스 중요도를 생각해보면 팀보다 회원이 더 중요한 느낌이지만,

 

하지만 자동차의 자체와 바퀴를 생각해보면 바퀴가 외래키가 있는 이다.

따라서 바퀴가 연관관계의 주인이 된다.

 

차체가 더 중요해 보이지만 연관관계의 주인은 단순히 외래키를 매핑한 바퀴를 선택하면 된다.

 

따라서 연관관계의 주인은 외래 키의 위치와 관련해서 정해야지 비지니스 중요도로 접근함하면절대 안된다!


 양방향 연관관계

 

Member.team   : 연관관계의 주인, 이 값으로 외래 키를 관리한다.

Team.members :  연관관계의 주인이 아니다. 따라서 저장시에 사용되지 않는다.

 

이처렁 양방향 연관관계에서는 결국 양쪽 다 신경 써야 한다.

Meber.setTeam() 메소드는 아래처럼 수정이 가능하다.

 

 

- 리팩토링 결과

✔ 연관관계 메서드

public void setTeam(Team team) {

 - 기존 관계 제거
if (this.team != null) {
this.team.getMembers().remove(this);
}

this.team = team;
team.getMembers().add(this);

}

 양방향 매핑 ?

 

단방향 매핑과 비교해서 양방향 매핑은 복잡하다.

연관관계의 주인도 정해야 하고, 두 개의 단방향 연관관계를 양방향으로 만들기 위해 로직도 잘 관리해야 한다.

 

중요한 사실은 연관관계가 하나인 단방향 매핑은 언제나 연관관계의 주인이라는 점이다.

양방향은 여기에 주인이 아닌 연관관계를 하나 추가했을 뿐이다.

 

결국 단방향과 비교해서 양방향의 장점은 반대방향으로 객체 그래프 탐색 기능이 추가된 것 뿐이다.

 

회원 -> 팀

member.getTeam()

 

팀 -> 회원

team.getMember()

 

주인의 반대편은 mappedBy 로 주인을 지정해야 한다.

그리고 주인은 반대편은 단순히 보여주는 일만 할 수 있다.

 

  • 단방향 매핑으로도 테이블과 객체의 연관관계 매핑은 완료 되었다.
  • 단방향을 양방향으로 만들면 반대방향으로 객체 그래프 탐색 가능이 추가 된다.
  • 양방향 연관관계를 매핑하려면 객체에서 양쪽 방향을 모두 관리해야 한다.

 

양방향 매핑은 매우 복잡하여서 비지니스 로직의 필요도에 따라 다르다.

우선 단방향 매핑을 사용하고 반대 방향으로 객체 그래프 탐색기능이 필요할 때

양방향을 사용하도록 코드를 추가해도 된다.


 

728x90
반응형

'개발중 > Java Persistence API (JPA)' 카테고리의 다른 글

JPA - 값 타입 컬렉션  (0) 2021.06.30
JPA - 즉시 로딩과 지연 로딩  (0) 2021.06.28
JPA / 프록시 알아보기  (0) 2021.06.28
식별 관계와 비식별 관계 구분  (0) 2021.06.25
JPA - 어노테이션 정리  (0) 2021.06.25