-
[JPA] 연관관계 매핑Back-end/JPA 2022. 4. 14. 09:59
# 연관관계가 필요한 이유
객체를 테이블에 맞춰 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.
- 테이블은 외래 키(FK)로 조인을 사용해 연관된 테이블을 찾는다.
- 객체는 참조를 사용해 연관된 객체를 찾는다.
# 연관관계 매핑시 고려사항 3가지
- 단방향 vs. 양방향
- 양방향 관계일 때의 연관관계의 주인
- 다중성
- @ManyToOne, @OneToMany, @OneToOne, @ManyToMany
1. 단방향 vs. 양방향
테이블
- 외래 키 하나로 양쪽 조인 가능
- 사실 방향이라는 개념이 없음
객체
- 참조용 필드가 있는 쪽으로만 참조 가능
- 한쪽만 참조하면 단방향
- 양쪽이 서로 참조하면 양방향
# 단방향 연관관계
객체 지향 모델링 - ORM 매핑
객체 지향 모델링 - 객체의 참조와 테이블의 외래 키를 매핑
@Entity public class Member { @Id @GeneratedValue private Long id; @ManyToOne @JoinColumn(name = "team_id") private Team team; ... }
객체 지향 모델링 - 연관관계 저장, 조회(객체 그래프 탐색), 수정
//저장 Team team = new Team(); team.setName("TeamA"); entityManager.persist(team); Member member = new Member(); member.setName("member1"); member.setTeam(team); //단방향 연관관계 설정, 참조 저장 entityManager.persist(member); //조회 Member findMember = entityManager.find(Member.class, member.getId()); Team findTeam = findMember.getTeam(); //참조를 사용해 연관관계 조회 //수정 Team teamB = new Team(); entityManager.persist(teamB); member.setTeam(teamB); //새로운 참조 설정
# 양방향 연관관계
- DB 테이블에는 변화가 없고, 엔티티에서만 List 컬렉션이 추가된다.
- 객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개이다.
- 단방향 매핑만으로도 이미 연관관계 매핑은 완료된 것이다.
- 양방향은 필요할 때 추가해도 된다. (어차피 테이블에 영향을 주지 않으니까)
- 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐이다.
- 테이블은 외래 키 하나로 양방향 연관관계(양쪽으로 조인 가능)를 가지고 두 테이블의 연관관계를 관리한다.
2. 양방향 관계일 때의 연관관계의 주인
- 양방향 관계 중 하나를 연관관계의 주인으로 지정해야 한다.
- 연관관계의 주인만이 외래 키를 관리한다. (DB 테이블에 외래 키 등록 및 수정)
- 연관관계의 주인 쪽에 값을 입력하지 않으면, DB 테이블의 FK 값이 null이 된다.
- 주인이 아닌 쪽은 읽기만 가능하고, mappedBy 속성으로 주인을 지정해야 한다.
- 외래 키가 있는 곳을 주인으로 정해라! (아래 예시에서는 Member.team이 연관관계의 주인이 됨)
양방향 매핑 예시
- Member.team이 연관관계의 주인일 때
- Member 엔티티 코드는 위와 동일하고, Team 엔티티에만 컬렉션이 추가된다.
@Entity public class Team { @Id @GeneratedValue private Long id; @OneToMany(mappedBy = "team") List<Member> members = new ArrayList<>(); ... }
3. 다중성
# 다대일(N:1) - 연관관계의 주인이 N인 쪽일 때
→ 외래 키가 있는 쪽이 연관관계의 주인
→ 양쪽을 서로 참조하도록 설정
# 일대다(1:N) - 연관관계의 주인이 1인 쪽일 때
→ 해당 경우는 일대다(1:N)에서 1이 연관관계의 주인인 경우이다.
→ DB 테이블의 일대다 관계에서는 항상 N 쪽에 외래 키가 존재한다.
→ 권장하지 않고, 다대일 양방향 관계를 사용하자
→ 위와 같은 매핑은 공식적으로 존재하지 않는다.
→ 읽기 전용 필드를 사용해 양방향처럼 사용하는 방법이다.
→ 권장하지 않고, 다대일 양방향 관계를 사용하자
# 일대일(1:1)
매핑방식1 - DB 주 테이블에 외래 키
→ @ManyToOne 단방향 매핑과 유사
→ 다대일 양방향 매핑처럼 테이블에 외래 키가 있는 곳이 연관관계의 주인이 된다.
→ 반대편은 mappedBy 속성으로 주인 설정
매핑방식2 - DB 대상 테이블에 외래 키
→ 대상 테이블에 외래 키가 존재한다.
→ 장점: 주 테이블과 대상 테이블을 1:1에서 1:N 관계로 변경할 때 테이블 구조 유지 가능
→ 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨
# 다대다(M:N)
매핑방식1 - @ManyToMany로 처리
→ @JoinTable로 중개 테이블을 지정한다.
→ 실무에서는 권장하지 않는다. (중개 테이블이 FK 이외의 필드를 가질 확률이 굉장히 높기 때문에)
매핑방식2 - 연결 테이블용 엔티티 추가 (주로 이것 사용!)
→ @ManyToMany를 @OneToMany와 @ManyToOne으로 나누어 처리한다.
'Back-end > JPA' 카테고리의 다른 글
[JPA] 값 타입 (0) 2022.04.28 [JPA] 프록시와 연관관계 관리 (0) 2022.04.28 [JPA] 상속관계 매핑과 @MappedSuperclass (0) 2022.04.27 [JPA] 엔티티 매핑 (0) 2022.04.11 [JPA] 등장 배경, 사용 이유, 간단 구동 방식 (0) 2022.03.31