다대일
- 데이터베이스 테이블의 일, 다 관계에서 외래 키는 항상 다쪽에 있다. => 연관관계의 주인은 항상 다쪽이다.
다대일 단방향 [N:1]
- 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long 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;
...
}
다대일 양방향 [N:1, 1:N]
- 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
public void setTeam(Team team) {
this.team = team;
if (!team.getMembers().contains(this)) {
team.getMembers().add(this);
}
}
...
}
- 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
public void addMember(Member member) {
this.members.add(member);
if (member.getTeam() != this) {
member.setTeam(this);
}
}
...
}
- 양방향은 외래 키가 있는 쪽이 연관관계의 주인이다. => JPA는 외래 키를 관리할 때 연관관계의 주인만 사용한다. 주인이 아닌 Team.members는 조회를 위한 JPQL이나 객체 그래프를 탐색할 때 사용한다.
- 양방향 연관관계는 항상 서로를 참조해야 한다.
- 편의 메소드는 한 곳에만 작성하거나 양쪽 다 작성할 수 있는데, 양쪽에 다 작성하면 무한루프에 빠지므로 주의해야 한다.
일대다
- 일대다 관계는 엔티티를 하나 이상 참조할 수 있으므로 자바 컬렉션인 Collection, List, Set, Map 중에 하나를 사용해야 한다.
일대다 단방향 [1:N]
- 일대다 단방향 관계는 JPA 2.0부터 지원한다.
- 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<>();
...
}
- 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
...
}
- 일대다 단방향 관계를 매핑할 때는 @JoinColumn을 명시해야 한다. 그렇지 않으면 JPA는 연결 테이블을 중간에 두고 연관관계를 관리하는 조인 테이블 전략을 기본으로 사용해서 매핑한다.
일대다 단방향 매핑의 단점
- 매핑한 객체가 관리하는 외래 키가 다른 테이블에 있다. => 연관관계 처리를 위한 UPDATE SQL을 추가로 실행해야 한다.
=> 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자.
일대다 양방향 [1:N. N:1]
- 일대다 양방향 매핑은 존재하지 않는다. 대신 다대일 양방향 매핑을 사용해야 한다. => 더 정확히 말하자면 양방향 매핑애서 @OneToMany는 연관관계의 주인이 될 수 없다.
- 일대다 양방향 매핑이 완전히 불가능한 것은 아니다. 일대다 단방향 매핑 반대편에 같은 외래 키를 사용하는 다대일 단방향 매핑을 읽기 전용으로 하나 추가하면 된다.
- 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<>();
...
}
- 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
private Team team;
...
}
- 이 방법은 일대다 단방향 매핑 반대편에 다대일 단방향 매핑을 읽기 전용으로 추가해서 일대다 양방향처럼 보이도록 하는 방법이다. => 일대다 단방향 매핑이 가지는 단점을 그대로 가진다.
'공부 기록 > Java' 카테고리의 다른 글
[이펙티브 자바 3/E] 아이템18 - 상속보다는 컴포지션을 사용하라 (0) | 2023.09.08 |
---|---|
[이펙티브 자바 3/E] 아이템17 - 변경 가능성을 최소화하라 (0) | 2023.09.07 |
[이펙티브 자바 3/E] 아이템16 - public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2023.08.26 |
[이펙티브 자바 3/E] 아이템15 - 클래스와 멤버의 접근 권한을 최소화하라 (0) | 2023.08.23 |
[JPA] 5장 - 연관관계 매핑 기초(3) - 양방향 연관관계 (0) | 2023.08.18 |