[JPA 기본] 5. 연관관계 매핑 기초
단방향 연관관계
목표
- 객체와 테이블 연관관계 차이를 이해한다.
- 객체의 참조와 테이블의 외래 키를 매핑한다.
용어
- 방향: 단방향 , 양방향
- 다중성: 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M)
- 연관관계의 주인(Owner): 양방향 연관관계에서는 관리의 주인이 필요하다.
객체를 테이블에 맞추어 모델링할 경우의 문제점.
- 식별자로 다시 조회하는데, 이는 객체 지향적인 방법은 아니다.
객체와 테이블의 데이터 검색 방식
- 테이블: 외래 키로 조인을 사용하여 연관 테이블을 찾는다.
- 객체: 참조를 사용하여 연관 객체를 검색
객체지향 모델링시 주의점
1:N에서 N의 위치를 파악해야한다.
예. TEAM, MEMBER -> MEMBER 가 N
양방향 연관관계와 연관관계의 주인
양방향 연관관계
A, B 두 엔티티가 서로 조회가능할 때를 일컫는다.
예) Member는 Team을 조회할 수 있고, Team은 Member를 조회할 수 있다.
양방향 연관관계의 주인
- 1:N에서 N이 주인이다.
- Member, Team 사이에는 Member가 주인.
// Member는 N이므로 ManyToOne사용
@ManyToOne
@JoinColumn(name="TEAM_ID")
private Team team;
// Team은 1:N에서 1. Member가 주인이다.
@OneToMany(mappedBy="team")
private List<Member> members = new ArrayList<>();
mappedBy
객체와 테이블이 관계를 맺는 차이
객체: 2개
- 회원 -> 팀
- 팀 -> 회원
테이블: 1개
- 회원 <-> 팀
문제점
team-members 관계를 업데이트하고자 할때, 어떻게 하면 좋을까?
양방향 매핑 규칙
- 객체 두 관계중 하나를 연관 관계 주인으로 지정.
- 주인만이 외래 키 관리
- 주인이 아닐 경우 읽기만 가능. mapped by 속성 사용하여 주인 지정.
양방향 연관관계 설정시 주의 사항
- 항상 양쪽에 값을 설정하자.
-> 연관관계 편의 메서드를 생성하면 실수할 일이 없다.
// 방법 1, 방법 2 중 하나만 택하여 사용하자. 둘 다 만들어두면 문제를 야기할 수도 있다.
// 방법 1.
class Member {
// field, method 생략
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this); // team을 넣을 때, member도 함께 설정하여 양방향 매핑 관계 성립
}
}
// 방법 2.
class Team {
// field, method 생략
pubic void addMember(Member member) {
member.setTeam(this);
members.add(member);
}
}
-> 양방향 매핑시 무한 루프를 조심할것.
--> toString()
---> 롬복에서 toString은 웬만하면 쓰지마라.
--> JSON 생성 라이브러리
---> contoller 에서는 Entity를 반환하지마라. DTO로 변경하여 반환하라.
-----> 이유: (1) 무한 루프 가능성 (Json으로 변경하면서 무한 루프) / (2) Entity를 변환하는 순간 API 스펙이 바뀐다.
양방향 매핑 요약
- 단방향 매핑만으로도, 이미 연관관계 매핑은 완료된 것이다. 양방향 매핑은 반대 방향으로 조회하는 기능이 추가된 것 뿐이다. JPQL에서 역방향으로 탐색할 일이 많다.가급적 단방향 매핑으로 끝내고 양방향 매핑은 필요할 때 추가하자. (테이블에 영향 없다)
실전 예제2 - 연관관계 매핑시작
(9:12) Member가 Orders를 포함하는 객체 구조는 좋은 형태가 아니다.
-> 설계를 잘못했다. 관심사를 못 끊어낸것. -> 왜 좋은 형태가 아닌지 이해 안감.