Spring/자바 ORM 표준 JPA프로그래밍

연관관계 매핑 기초

hyun-1200 2022. 5. 7. 17:06

<목표>

  • 객체와 테이블 연관관계의 차이를 이해
  • 객체의 참조와 테이블의 외래 키를 매핑

<용어이해>

  • 방향(Direction) : 단방향, 양방향
  • 다중성(Multiplicity): 다대일(N:1) , 일대다(1:N), 일대일(1:1), 다대다(N:M) 이해
  • 연관관계의 주인(Owner) : 객체 양방향 연관관계는 관리 주인이 필요

1. 연관관계가 필요한 이유

- 객체지향 설계의 목표는 자율적인 객체들의 협력공동체를 만드는 것이다. by조영호(객체지향의 사실과 오해) 

- 객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력관계를 만들 수 없다.

  • 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
  • 객체는 참조를 사용해서 연관된 객체를 찾는다.
  • 테이블과 객체 사이에는 이런 큰 간격이 있다. 

 - 참조 대신 외래키를 그대로 사용하였다 -> 객체를 테이블에 그대로 맞추어 모델링 

 

 

- Member 에 team_id를 저장하기 위해서 team객체의 아이디를 받아와서 다시 저장하는것은 객체 지향적인 방법이 아니다. 

 

 

2. 단방향 연관관계

 

- 객체의 참조와 테이블의 외래 키를 매핑하였다 -> 객체 지향 모델링

- Team에서 getId를 받아와서 teamId를 저장하는 방법보다 훨신 객체 지향적이다.

  member.setTeamId(team.getId()) 

 

 

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

양방향 매핑 ( Member 엔티티에서도 team 참조, Team 엔티티에서도 member 참조 )

-Member 엔티티는 단방향과 동일하게

- Team 엔티티에서 @OneToMany 추가후 mappedBy = "team" .

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

 

 mappedBy 

- 객체와 테이블이 관계를 맺는 차이를 이해해야 한다.

- JPA의 멘붕 난이도.. 

 

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

  • 테이블 연관관계 = 1개
    • 회원<-> 팀의 연관관계 1개 (양방향)
  • 객체 연관관계 = 2개
    • 회원 -> 팀 연관관계 1개 (단방향)
    • 팀 -> 회원 연관관계 1개 (단방향)

* 객체의 양방향 관계

  • 객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개다.
  • 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 한다. 
    • A -> B 로 가고 싶을 때 : a.getB()
    • B -> A 로 가고 싶을 때: b.getA()  

 

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

 

따라서, 테이블과 객체의 관계 맺는 차이 때문에

객체는 객체의 두 관계 중 하나를 연관관계의 주인으로 정해야한다. 

 

아래와 같은 그림에서는 team으로 연관관계의 주인으로 하는게 좋을까? members를 연관관계의 주인으로 하는게 좋을까? 

 

* 연관관계의 주인 (Owner)

 

양방향 매핑 규칙
  • 객체의 두 관계 중 하나를 연관관계의 주인으로 지정
  • 연관관계의 주인만이 외래키를 관리 (등록, 수정)
  • 주인이 아닌쪽은 읽기만 가능
  • 주인은 mappedBy 속성 사용 X
  • 주인이 아니면 mappedBy 속성으로 주인 지정 
누구를 연관관계의 주인으로 정할 것인가? 

  • 외래 키가 있는 곳을 주인으로 정해라.
  • 여기서는 Member.team이 연관관계의 주인
  • ManyToOne "다" 쪽에 연관관계의 주인으로 해라. 

 

 

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

- 연관관계의 주인에 값 설정은 필수이며, 주인이 아닌 방향에도 값 설정을 해 주는 것이 좋다. 

   team.getMembers().add(member)  // 연관관계의 주인이 아닌 방향에도 값 설정 

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

- 실수로 까먹는 경우가 생길 수 있으므로, 연관관계 편의 메서드를 사용하자.

- ex. Member객체 안에 member와 Team을 둘다 저장하는 메서드를 만들어 사용하자. member.changeTeam(team) 

 

* 주의 ! 양방향 매핑 시에 무한 루프를 조심하자. 

- toString(), lombok, JSON 생성 라이브러리 

 

* 단방향 매핑만으로 연관관계 매핑 완료할 수 있고, 추가로 양방향이 필요할때 나중에 추가하면 됨.

* JPQL에서 역방향으로 탐색할 일이 많음. 

 

 

( 해당 글은 인프런- 자바 ORM 표준 JPA 프로그래밍 수업 및 제공되는 자료를 바탕으로 작성하였습니다. ) 

'Spring > 자바 ORM 표준 JPA프로그래밍' 카테고리의 다른 글

고급매핑 : 상속관계 매핑 /@MappedSuperclass  (0) 2022.05.10
다양한 연관관계 매핑  (0) 2022.05.08
엔티티 매핑  (0) 2022.05.06
영속성 컨텍스트  (0) 2022.05.05
JPA 소개  (0) 2022.05.05