연관관계 매핑 기초
1. 예제 시나리오
회원과 팀이 있다.
회원은 하나의 팀에만 소속될 수 있다.
회원과 팀은 다대일 관계이다.
객체를 테이블에 맞추어 모델링

객체간 연간관계가 없기 때문에, 테이블 설계에 의존된 코드를 작성하게 된다. (객체지향적인 코드가 아니다..)
문제점
객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 맺을 수 없다.
테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
객체는 참조를 사용해서 연관된 객체를 찾는다.
테이블과 객체 사이에는 큰 간격이 존재한다..
2. 단방향 연관관계

참조를 통해서 연관관계 조회가 가능하다. (객체 그래프 탐색)
연관관계 수정 또한 객체지향적으로 가능하다.
3. 양방향 연관관계와 연관관계의 주인1 - 기본
⁉️ 결론부터 이야기하자면, 일단 JPA 설계라는 것은 단방향 매핑으로 마무리가 되어야 한다! ⁉️ -> 매우 중요한 이야기이다❗
단방향 매핑을 잘 하고 양방향은 필요할 때 추가하면 된다.
양방향 매핑
테이블의 경우, 외래키(JOIN)를 통해서 연관관계를 맺는다면, 양방향으로 관계를 맺는다.
외래키 하나로 양방향 연관관계가 있는 것이다!
양방향 매핑을 하더라도, 테이블 구조는 변하지 않는다!
문제는 객체다.. 객체의 경우 각 객체마다 연관관계가 있는 객체를 인자로 두어야 한다.
Member는TeamTeam은Member

객체와 테이블이 관계를 맺는 차이

객체 연관관계 = 단방향 연관관계 2개
회원 -> 팀 연관관계 1개(단방향)
팀 -> 회원 연관관계 1개(단방향)
객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개이다.
객체를 양방향으로 참조하려면 단뱡향 연관관계 2개를 만들어야 한다.
테이블 연관관계 1개
회원 <-> 팀의 연관관계 1개(양방향)
테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다.
MEMBER.TEAM_ID외래 키 하나로 양방향 연관관계를 가진다. (양쪽으로 조인이 가능하다)
딜레마 : 객체의 어떤 값으로 외래 키를 매핑해야 하는가?
결론적으로, 둘 중 하나로 외래 키를 관리해야 한다!

연관관계 주인(Owner)
양방향 매핑 규칙
객체의 두 관계 중 하나를 연관관계 주인으로 지정해야 한다.
연관관계의 주인만이 외래 키를 관리(등록, 수정) 한다.
주인이 아닌 쪽은 읽기만 가능하다.
주인이 아닌 쪽이
mappedBy속성을 사용해 주인을 지정해야 한다.
누구를 주인으로 해야 하는가?
외래키가 있는 곳을 주인으로 정하자!
이렇게 해야만 논리적 혼란을 방지할 수 있다.
예를 들어,
Member값을 변경하는데,Team업데이트 쿼리가 나간다면? 서비스를 파악하기 너무 어렵다..
여기서는
Member.team이 연관관계의 주인이다.

4. 양방향 연관관계와 연관관계의 주인2 - 주의점
양방향 매핑시 가장 많이 하는 실수
주인이 아닌 객체에서 연관관계의 주인의 값을 입력하지 않는다.
mappedBy로 설정한 인자에 대해서는 JPA 가 데이터 변경시 해당 인자를 참고하지 않는다.때문에,
team.getMembers().add(member);을 한다고 한들 데이터는null값으로 들어간다.

양방향 매핑시 연관관계의 주인에 값을 입력해야 한다.

순수한 객체 관계를 고려하면 항상 양쪽 다 값을 입력해야 한다.
위 코드가 DB 입장에서는 아무런 문제가 없는 코드지만, 만약 순수한 객체 관계를 고려하지 않았기 때문에, 애플리케이션 코드 단에서 논리적 오류가 발생한다.
아래 코드에서는 디비에는 값이 들어가지만,
객체 그래프 내에서는
team에member가 설정되지 않았기 때문에,findTeam.getMembers()의 값이 없다.
이 경우 2가지 문제가 발생한다.
애플리케이션 코드 내(객체 그래프)에서 논리적 오류가 발생한다.
JPA 가 알아서 값을 입력해줄 것 같지만, 아니다..
순수한 자바로 테스트 작성시 논리적 오류가 발생한다.
양방향 연관관계 주의점
1. 순수한 객체 상태를 고려해서 항상 양쪽에 값을 설정하자.
2. 연관관계 편의 메서드를 생성하자.
순수한 객체 상태를 고려해서 양쪽에 값을 설정해야 하지만, 까먹는 경우가 있다.
때문에, .setTeam() 내부에 연관관계를 맺어주는 코드를 추가해 연관관계를 누락할 가능성을 줄여준다.
3. 양방향 매핑시에 무한 루프를 조심하자. (예: toString(), lombok, JSON 생성 라이브러리)
toString(), lombok, JSON 생성 라이브러리)양쪽에서 각각 서로를 호출하는 경우 무한 루프가 발생될 수 있다.
5. 실전 예제2 - 연관관계 매핑 시작
테이블 구조
테이블 구조는 이전과 같다.

객체 구조
참조를 사용하도록 변경

Last updated