JPA/Hibernate 연관관계 매핑

메밀·2023년 2월 7일
0

(김영한, <자바 ORM 표준 JPA 프로그래밍>의 5장 연관관계 매핑 기초를 요약한 글입니다.)

0. 시작하며

핵심 키워드: 방향, 다중성, 연관관계의 주인

  • 방향: 단방향, 양방향
  • 다중성: 다대일, 일대다, 일대일, 다대다
  • 연관관계의 주인: 양방향 연관관계 시 주인을 정해야 한다

1. 단방향 연관관계

1) 다대일 단방향

  • 회원과 팀의 예시

객체 연관관계와 테이블 연관관계

  • 회원 객체는 Member.team 필드로 팀 객체와 연관관계를 맺지만, team에서 member로 접근하는 필드는 없다.
  • 반면, member 테이블과 team 테이블은 team_id 외래키를 통해 둘 모두 접근 가능하다.
    (member JOIN team, team JOIN member 둘 다 가능)

=> 참조를 사용하는 객체의 연관관계는 단방향이지만, 외래키를 사용하는 테이블의 연관관계는 양방향이다.

cf) 객체 그래프 탐색: 참조를 사용하여 객체 연관관계를 탐색하는 것

연관관계 매핑 어노테이션

어노테이션설명
@JoinColumn(name="")name 속성에 매핑할 외래키 이름 지정
@ManyToOne다대일 관계라는 매핑 정보 (다중성) cf) fetch(페치 전략)

2. 연관관계 사용 - CRUD

생략

3. 양방향 연관관계

Member.team, Team.members(일대다므로 컬렉션 사용)

1) 양방향 연관관계 매핑

public class Member {
	/* 생략 */
    
    @ManyToOne
    @JoinColumn(name="team_id")
    private Team team;
}

public class Team {
	/* 생략 */
    
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
}

2) 일대다 컬렉션 조회

이제 team.getMembers()로 팀 -> 회원 객체 그래프 탐색이 가능하다.


4. 연관관계의 주인 - mappedBy

  • 엄밀히 말하면 객체엔 양방향 연관관계가 없다.

  • 서로 다른 단방향 2개를 묶어 양방향처럼 보이게 한 것.

  • 테이블은 외래키 하나로 두 테이블의 연관관계를 관리 (회원 ↔ 팀)

  • 객체 연관관계: 회원 → 팀, 팀 → 회원

  • 엔티티를 단방향으로 매핑하면 참조를 하나만 사용하므로, 이 참조로 외래키 관리

  • 그러나 양방향으로 매핑하면 회원 → 팀, 팀 → 회원 두 곳에서 서로를 참조

  • 즉, 객체의 참조는 둘인데 외래키는 하나인 상황

  • 두 연관관계 중 하나를 정해서 테이블의 외래키를 관리 => 연관관계의 주인

1) 연관관계의 주인

연관관계의 주인만이 DB 연관관계와 매핑되어 외래키를 관리(등록, 수정, 삭제) 할 수 있다.
주인이 아닌 쪽은 읽기만 할 수 있다.
어떤 연관관계를 주인으로 정할지는 mappedBy 속성을 사용하면 된다.

  • 주인은 mappedBy 속성을 사용하지 않는다.
  • 주인이 아니면 mappedBy 속성을 사용해서 속성의 값으로 연관관계의 주인을 지정해야 한다.

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

위의 예시에서 Member.team을 주인으로 선택하면, 자기 테이블에 있는 외래키를 관리하면 된다.
Team.members를 주인으로 선택하면 물리적으로 전혀 다른 테이블의 외래키를 관리해야 한다.


## 2) 연관관계의 주인은 외래 키가 있는 곳 연관관계의 주인만 데이터베이스의 연관관계와 매핑되고 FK를 관리할 수 있다. 주인이 아닌 반대편은 읽기만 가능하고 외래키를 변경하지는 못한다.

5. 양방향 연관관계 저장

public void testSave(){
	// 팀1 저장
	Team team1 = new Team("team1", "팀1");
    em.persist(team1);
    
    // 회원1 저장
    Member member1 = new Member("member1", "회원1");
    member1.setTeam(team1); // 연관관계 설정 member1 -> team1
    em.persist(member1);
}

member 테이블의 team_id(FK)에 팀의 기본키 값이 저장된다.

양방향 연관관계에서 주인이 아닌 방향은 값을 설정하지 않아도 데이터베이스에 외래키 값이 정상 입력된다.
즉, 아래와 같은 코드는 필요 없다.

team.getMembers().add(member1);

6. 정리

단항뱡 매핑은 언제나 연관관계의 주인
양방향은 주인이 아닌 연관관계를 하나 추가한 것
-> 반대방향으로 객체 그래프 탐색 기능이 추가된 것

주인의 반대편은 mappedBy를 사용하여 주인을 지정
단순히 보여주는 일(객체 그래프 탐색)만 할 수 있다.

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

단방향은 항상 외래키가 있는 곳을 기준으로 매핑하면 된다.
연관관계의 주인 == 외래키 관리자

0개의 댓글