단방향 연관관계
//단방향
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
// 어노테이션은 현재 클래스 (Member) 시점에서 해석하면 된다.
@ManyToOne // Many(자신)을 One과 맵핑
@JoinColumn(name = "team_id") // 어떤 컬럼을 PK로 할건지
private Team team;
}
public class Team {
@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
@Column(name = "team_name")
private String name;
}
양방향 연관관계
// 양방향 -> 연관관계의 주인이 생긴다.
// 주인 : PK를 갖고 있는 쪽, @ManyToOne
// 주인아닌쪽 : List를 갖는다. @OneToMany(mappedBy = "")
// 1. 주인
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
// 어노테이션은 현재 클래스 (Member) 시점에서 해석하면 된다.
@ManyToOne // Many(자신)을 One과 맵핑
@JoinColumn(name = "team_id")
private Team team;
}
// 2.주인이 아닌 쪽
public class Team {
@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
@Column(name = "team_name")
private String name;
// 양방향인경우 주인이 아닌 쪽에 List 추가한다
// 주인을 조회할 때만 사용한다. ( 수정, 삭제 XX)
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<>();
}
(중요) 양방향 연관관계에서 연관 관계 주인이란?
- 외래키가 있는 곳(1:N에서 N) 을 연관관계 주인으로 한다.
- 연관관계의 주인만이 외래키를 관리해야함(외래키 등록, 외래키 수정)
@Entity
public class Team { // 주인 아닌 쪽
@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
@Column(name = "team_name")
private String name;
// 양방향인경우 아래 추가
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<>();
}
- 주인이 아닌쪽에 @OneTomany(mappedBy = "")를 써서 members를 읽기 전용으로 만든다. (가짜 매핑)
- mappedBy로 members 를 “읽기 전용” 을 만든다는 것의 의미?
- "연관관계"가 readonly 가 된다는 것임
- List<Member> members에 새로운 team을 add 하거나 기존 객체를 다른 객체로 변경해도, 실제 DB에는 이러한 연관관계 변경이 반영되지 않는다.
- 헷갈렸던 부분 : "읽기 전용이라고 해서 team으로 member에 접근해서 member 값을 수정할 수 없다는건가 ?? 했는데 그거 아님. 객체 내 값은 write 가능 !
- mappedBy로 members 를 “읽기 전용” 을 만든다는 것의 의미?
@Entity
public class Team { // 주인이 아닌 객체
// (생략)
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<>();
}
// 이렇게 mappedBy로 가짜 매핑해주게 되면
// (1)연관관계가 readonnly가 된다.
// -> 코드 상으로는 새로운 연관관계를 형성한 듯 보이지만, 실제 DB를 보면 뉴비가 team에 소속되지 않음
team.getMembers().add(new Member("뉴비"))
// (2) 주의 : 값이 readonly(변경할 수 X)된다는 게 아니다. 값은 updatable : 변경사항이 DB에 반영됨
team.getMembers().name = "홍길동 "
양방향 연관관계 주의할 점 : 무한 루프 조심
무한 루프는 toString(), lombok, json 생성 라이브러리 사용 시 주로 발생
해결법 : 컨트롤러에 엔티티 반환하지 말기. (DTO로 변환후 리턴)
연관관계 편의 메서드는 어디에 만들까?
양방향 연관관게인 경우, 양쪽의 연관관계를 동시에 맺어주는 연관관계 편의 메서드를 만들어서 사용하면 편하다.
연관관계 편의 메서드의 위치는 둘 중 비즈니스 로직 상 더 중요한 곳으로 한다.
→ 즉, 주인이 아닌 곳에 위치해도 된다.
양쪽 모두에 편의 메서드를 정의해도 되나?
→ 한쪽에만 정의하는 게 좋음
→ 양쪽에 정의해두면 상호 참조로 인해 무한루프 생길 수 있기 때문
단방향 매핑만으로도 충분하다.
- 단방향 만으로도 DB 테이블 간에 연관관계 매핑이 설정된다.
- 양방향은 그냥 JPA를 쓸때, 객체 시점에서 반대 방향을 편하게 조회하려고 만들어 진 것이다..
- 단방향 -> 양방향은 테이블 모양에 영향을 주지 않기 때문에, 설계부터 굳이 양방향으로 할 필요 없다.
- 나중에 서비스 개발하다가 필요해지면 그때 양방향으로 만들면 된다.
'TIL' 카테고리의 다른 글
SLOW QUERY 란? 성능 개선은 어떻게 이루어지는지 (0) | 2024.05.03 |
---|---|
함수 명명시 자주 사용되는 동사 표현 정리 (유의어, 반의어) (1) | 2024.05.02 |
JPA 연관관계 매핑 (0) | 2024.04.27 |
Java 기초 문법(2) (0) | 2024.02.19 |
Java 기초 문법 (1) (0) | 2024.02.18 |