(김영한, <자바 ORM 표준 JPA 프로그래밍>의 5장 연관관계 매핑 기초를 요약한 글입니다.)
=> 참조를 사용하는 객체의 연관관계는 단방향이지만, 외래키를 사용하는 테이블의 연관관계는 양방향이다.
cf) 객체 그래프 탐색: 참조를 사용하여 객체 연관관계를 탐색하는 것
어노테이션 | 설명 |
---|---|
@JoinColumn(name="") | name 속성에 매핑할 외래키 이름 지정 |
@ManyToOne | 다대일 관계라는 매핑 정보 (다중성) cf) fetch(페치 전략) |
생략
Member.team, Team.members(일대다므로 컬렉션 사용)
public class Member {
/* 생략 */
@ManyToOne
@JoinColumn(name="team_id")
private Team team;
}
public class Team {
/* 생략 */
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
이제 team.getMembers()로 팀 -> 회원 객체 그래프 탐색이 가능하다.
엄밀히 말하면 객체엔 양방향 연관관계가 없다.
서로 다른 단방향 2개를 묶어 양방향처럼 보이게 한 것.
테이블은 외래키 하나로 두 테이블의 연관관계를 관리 (회원 ↔ 팀)
객체 연관관계: 회원 → 팀, 팀 → 회원
엔티티를 단방향으로 매핑하면 참조를 하나만 사용하므로, 이 참조로 외래키 관리
그러나 양방향으로 매핑하면 회원 → 팀, 팀 → 회원 두 곳에서 서로를 참조
즉, 객체의 참조는 둘인데 외래키는 하나인 상황
두 연관관계 중 하나를 정해서 테이블의 외래키를 관리 => 연관관계의 주인
연관관계의 주인만이 DB 연관관계와 매핑되어 외래키를 관리(등록, 수정, 삭제) 할 수 있다.
주인이 아닌 쪽은 읽기만 할 수 있다.
어떤 연관관계를 주인으로 정할지는 mappedBy 속성을 사용하면 된다.
연관관계의 주인을 정한다는 것은 외래키 관리자를 선택하는 것!
위의 예시에서 Member.team을 주인으로 선택하면, 자기 테이블에 있는 외래키를 관리하면 된다.
Team.members를 주인으로 선택하면 물리적으로 전혀 다른 테이블의 외래키를 관리해야 한다.
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);
단항뱡 매핑은 언제나 연관관계의 주인
양방향은 주인이 아닌 연관관계를 하나 추가한 것
-> 반대방향으로 객체 그래프 탐색 기능이 추가된 것
주인의 반대편은 mappedBy를 사용하여 주인을 지정
단순히 보여주는 일(객체 그래프 탐색)만 할 수 있다.
단방향은 항상 외래키가 있는 곳을 기준으로 매핑하면 된다.
연관관계의 주인 == 외래키 관리자