728x90
엔티티들은 대부분 다른 엔티티와 연관 관계가 있습니다.
객체와 테이블의 연관 관계에서 가장 큰 두가지의 차이는
- 객체는 참조(레퍼런스)로 연관관계를 맺습니다.
- 테이블은 외래 키를 사용해서 조인(join)을 통해 연관관계를 맺습니다.
이러한 차이점 안에서 객체의 참조와 테이블의 외래키를 매핑하는 방법을 정리하겠습니다.
단방향 연관관계
단방향 연관관계는 회원 -> 팀 또는 팀 -> 회원 과 같이 둘 중 한 쪽만 참조하는 것을 단방향 관계라고 말합니다.
member와 team이 다음과 같이 연관 관계를 맺고 있습니다.
@Entity
public class Member {
@Id @GeneratedValue
@Column(name= "MEMBER_ID")
private String id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
}
- 객체의 연관 관계 설정을 위해 Member 객체의 Member.team 필드를 사용하였습니다.
- 이것은 테이블에서는 MEMBER 테이블에 TEAM_ID를 외래키로 사용한 것입니다.
- Team과 Member는
1 대 다
관계이기 때분에@ManyToOne
애노테이션을 사용해서 표현하였습니다. @JoinColumn
을 사용하여 외래 키를 매핑 하였습니다.@JoinColumn
의name
속성을 이용해서 외래키의 이름을 지정합니다.
양방향 연관관계
양방향 연관관계는 단방향 연관관계와 다르게 서로 참조하는 구조를 가지고 있습니다.
양방향 연관관계는 다음과 같은 특징이 있습니다.
- 테이블의 연관관계는
외래 키
한개로 양방향 연관관계가 구현이 됩니다.- DB에서는 방향이라고 이야기 할 것이 없습니다.
외래키 한 개
로JOIN
을 통해 양방향으로 조회를 할 수 있습니다.
- 객체의 연관관계에서 양방향 연관관계는 사실 2개의 단방향 연관관계 입니다.
@Entity
public class Team{
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<Member>();
}
- 객체의 연관관계 : 2개
- Member -> Team
- Team -> Member
- 테이블 연관관계 : 1개
- Member <-> Team / 외래 키 설정된 양방향
Team 엔티티에서 Member로 매핑을 작성하여 양방향 관계를 완성한 것을 확인 할 수 있습니다.
연관 관계의 주인
위의 코드에서 @OneToMany 애노테이션 안에 mappedBy= "team"
이라는 속성이 있습니다.
mappedBy 속성은 양방향 연관관계에서 주인을 설정하는 속성입니다.
엔티티의 양방향 연관관계에서 주인을 설정하는 이유는 다음과 같습니다.
- 양방향 관계에서 객체에서 참조는 두개인데 테이블은 외래키 하나로 관리합니다.
- 두 객체 연관관계 중에 하나를 연관관계의 주인으로 정해서 외래키를 관리합니다.
위의 코드에서 @OneToMany(mappedBy = "team")
의 의미는
Member 엔티티에 있는 private Team team
을 연관관계의 주인으로 설정한다는 뜻입니다.
결론은 연관 관계의 주인을 정한다는 것은 외래 키 관리자를 선택하는 것입니다.
연관 관계 주인 규칙
연관 관계의 주인으로 정하고 외래키를 관리하기 위해서는 다음과 같은 규칙을 따라야 합니다.
- 연관 관계의 주인만이 외래키를 관리해야 합니다.
- 데이터의 등록 및 수정 등은 연관 관계의 주인을 통해서만 이루어져야합니다.
- 연관 관계의 주인이 아닌 쪽은 읽기만 가능합니다.
- 연관 관계의 주인은 mappedBy 속성을 사용하지 않습니다.
- 연관 관계의 주인이 아닌 쪽은 mappedBy 속성을 사용하여 주인을 지정해줍니다.
실전 주인 설정 방법
- DB 설계시에 외래 키가 있는 곳을 주인으로 설정하는 것이 좋습니다.
- 1 대 다 관계에서는 "다" 쪽이 연관관계의 주인이 됩니다.
양방향 매핑시 주의점
- 연관 관계의 주인인 곳에 값을 입력하지 않고, 주인이 아닌 곳에 입력하는 경우
- 주인이 아닌 곳에는 등록, 수정이 되지 않으므로 주인인 곳에 입력해야 합니다.
- 그러나 영속성 컨텍스트에 입력한 후에 바로 조회를 하게 된다면 1차 캐시에 데이터가 나오므로 연관 관계가 형성되지 않았을 가능성이 있습니다.
- 이와 같은 순순 객체 상태를 고려하여 항상 양쪽에 값을 설정해주는 것이 안전합니다.
- addMember() 와 같은 연관 관계 편의 메서드를 작성하여 양쪽에 값을 설정합니다.
- 양방향 매핑시에 무한 루프가 생길 수 있습니다.
- to_string()을 사용시에 서로 계속해서 참조하는 무한루프가 발생할 수 있습니다.
정리
- 사실 단방향 매핑만으로도 연관관계 매핑은 완료됩니다. 양방향 매핑은 필요할 때만 구현합니다.
- 양방향 매핑은 반대 방향으로 조회 기능이 추가 된 것일 뿐입니다.
- 단방향 매핑이 잘 되어 있는 상태에서 양방향을 추가한다고 해도 테이블은 단방향 상태 그대로 유지 됩니다.(테이블에 영향이 가지 않습니다.)
- 연관 관계의 주인은 비즈니스 로직이 아니라 외래 키의 위치를 기준으로 정해야합니다.
'프로그래밍 > JPA' 카테고리의 다른 글
[ JPA ] 다양한 연관 관계 매핑 (0) | 2022.04.14 |
---|---|
[ JPA ] 영속성 컨텍스트란? (0) | 2022.03.28 |
[ JPA ] JPA란? (0) | 2022.03.27 |