연관관계
객체의 연관관계와 테이블의 연관관계는 서로 간극이 존재한다.
객체는 참조를 사용하여 연관된 객체를 찾는다.
테이블은 외래키를 사용하여 연관된 테이블을 찾는다.
따라서, ORM에서 "객체의 참조와 테이블의 외래키를 매핑" 하는 것이 중요하다.
양방향 연관관계에서는 연관관계의 주인 설정이 중요하다.
연관관계의 주인은 "외래키의 위치" 와 같다.
Member 와 Team의 연관관계에서 주인은 외래키를 가지고 있는 "Member" 이다.
연관관계의 주인은 '주', 주인이 아닌 것은 '종'으로 표기하겠다.
ex) 주(Member) / 종(Team)
* 주(Member) -> 종(Team) 연관관계 *
@ManyToOne : Member.class의 입장에서, Team.class를 본 관점.
@JoinColumn(name = "TEAM_ID") : "외래키(FK)" 를 조인 컬럼으로 사용한다는 의미
* 종(Team) -> 주(Member) 연관관계 (읽기 전용) *
@OneToMany(mappedBy = "team") : Team.class 의 입장에서, Member.class를 바라본 관점.
mappedBy 는 연관관계 중 '종(Team)' 이 사용하는 속성 = 해당 필드의 소유주가 누군지 알려줌.
[ex) teamQ의 소유주는 memberA, memberB, memberC 이다.]
* 연관관계에서 '종'에게 값을 입력하는 경우 **문제발생** *
1. member를 저장할 때, team을 지정하지 않고 저장
2. team을 저장
3. 연관관계(종 = 주인이 아님) 에게 값을 입력
team.members 에 member 객체를 추가
그러나, 예상과 달리 값이 정상적으로 입력되지 않았다.
양방향 연관관계에서 주(Member) -> 종(Team) 으로의 값 입력은 가능하다.
그러나, 종(Team) -> 주(Member) 로의 연관관계는 "읽기 전용" 으로 만 가능하다.
* 연관관계에서 '주'에게 값을 입력하는 경우 *
주(Member) -> 종(Team) 으로의 값 입력은 정상적으로 작동하는 것을 볼 수 있다.
=> 연관관계의 '주'에게 값 입력을 해야함
** 양방향 연관관계에서 올바른 값 입력 방식 **
양방향 매핑시 연관관계의 주인에 값을 입력해야 한다.
그러나 순수한 객체 관계를 고려하면, !항상 양쪽 다 값을 입력해야 한다!
1. 주(memberA) -> 종(teamQ) 연관관계 로만 값을 입력하는 경우 ( ' 주(memberA) '에게만 값을 입력하는 경우 )
1. 객체 teamQ를 생성하고, persist 한다.
2. 객체 memberA를 생성하고, '주(memberA)' 에게 값을 입력한다. + persist 한다.
+) '종(teamQ) 에게 값을 입력하지 않음.'
3. teamQ.members 리스트의 사이즈를 출력한다.
members.size = 0 인것을 볼 수 있다!
이유 : teamQ와 memberA 순서로 persist 하면, 영속성 컨텍스트의 1차 캐시에 입력된다.
별도의 em.flush() 등 영속성 컨텍스트의 초기화가 없이, teamQ의 요소를 호출한다면, 1차 캐시에서 이를 반환하게 된다.
따라서, 처음 영속성 컨텍스트에 등록될 때, members 리스트가 비어있었기 때문에, 그대로 빈 리스트가 반환되게 되는 것이다.
이러한 문제를 해결하는 방법은 다음과 같다.
2. 양방향 매핑 모두 값을 입력하는 경우 ( '주(memberA)->종(teamQ) , 종(teamQ)->주(memberA)' )
양방향 매핑에 모두 값을 입력해 보자.
이 경우, "teamQ.getMembers().add(memberA);" 는 실제로 값이 입력되지는 않는다. 그러나 teamQ의 1차 캐시 값을 갱신하는 효과가 있다.
따라서, 갱신된 1차 캐시 teamQ에서 리스트를 반환하기 때문에, 문제를 해결할 수 있다.
하지만, 항상 양뱡향 매핑에 모두 값을 입력하는 것은 굉장히 번거로운 일이 아닐 수 없다.
이를 효율적으로 하기 위해 "연관관계 편의 메서드" 를 만든다.
'연관관계 편의 메서드'는 값을 양방향으로 넣을 수 있도록 하나의 메서드로 구성하는 것을 의미한다.
이와 같이 연관관계 편의 메서드를 구성하는 것을 추천한다.
※ 연관관계편의메서드는 기존 제공되는 set 메서드와 다른 이름을 사용하는 것을 권장한다.
중요 포인트
0. 양방향 연관관계 = '주'->'종' 단방향 연관관계 + '종' -> '주' 조회 기능
1. 양방향 연관관계의 주인은 '외래키의 위치'
2. 양방향 매핑에 모두 값을 입력 필수! (연관 관계 편의 메서드를 활용!)
'Spring > JPA' 카테고리의 다른 글
[JPA - 8] 상속관계 매핑 / @MappedSuperclass (0) | 2023.12.02 |
---|---|
[JPA - 7] 다양한 연관관계 매핑 (0) | 2023.12.01 |
[JPA - 5] Entity Mapping (0) | 2023.11.25 |
[JPA - 4] 영속성 컨텍스트 (Persistence Context) - 내부 동작 방식 (0) | 2023.11.24 |
[JPA - 3] JPA 구동 방식 / 간단한 JPA를 이용한 데이터 조작 (1) | 2023.11.20 |