기록과 정리

JPA 연관관계 매핑 ( 단방향 , 양방향 ) 본문

IT/JPA

JPA 연관관계 매핑 ( 단방향 , 양방향 )

zepetto 2021. 2. 16. 13:54

이 글은 김영한님의 자바 ORM 표준 JPA 프로그래밍 강의를 참고하였습니다.

 

www.inflearn.com/course/ORM-JPA-Basic/lecture/21699?tab=curriculum

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그

www.inflearn.com

 

JPA 공부를 하면서 어려운 단계에 도착한 것 같다. 바로 연관관계에 대한 매핑이다. 그래서 연관관계 매핑에 대해 정리를 해보려합니다.

 

연관관계란?

 

우선 연관관계가 필요한 이유를 살펴봅시다.

테이블은 Join을 이용하여 서로의 연관 관계를 만들고 객체는 참조를 통해 관계를 형성합니다.

Entity를 객체가 아닌 테이블 관점에서 바라보게 되면 객체 지향적인 방법이 아닐 뿐더러 객체를 테이블에 맞추어 모델링하는 방식이 됩니다. 객체끼리는 전혀 연관관계가 없죠. 

 

따라서 객체는 객체와 연관시켜주는 연관관계를 형성할 필요가 있습니다.

객체의 연관관계
테이블의 연관관계

연관관계의 종류 

 

객체 연관 관계에는 크게 2가지가 존재합니다.

 

1. 단방향 연관관계

단방향 연관관계시 주의점은 Phone이라는 객체를 참조하기 위해서 @ManyToOne이라는 어노테이션을 사용한다. JPA에서 관리하겠다라고 알려주며 실제로 테이블에서 Join하는 FK를 옵션값으로 naming 해준다. 

2. 양방향 연관관계

사실 양방향인 객체의 연관관계는 없습니다. 정확히 말하면 단방향을 양쪽에서 만들어주는것을 양방향이라는 단어로 정의한 것이죠. 

 

단방향 = iPhone -> Phone 

양방향 = iPhone <-> Phone (x) ,  iPhone -> Phone + Phone -> iPhone ( o )

 

또한 양방향 연관관계에 있어서 연관관계에 우위(?)를 점하는 연관관계의 주인이 있습니다. 마치 테이블의 연관관계에서 FK를 가지고 있는 테이블처럼요.

양방향 객체 관계

 

양방향 매핑이어도 테이블의 연관관계는 변함이 없다.

 

소스로 살펴보면 위 iPhone 의 소스는 동일합니다. 왜냐 단방향은 마찬가지이기 떄문이죠. 여기서 Phone 객체만 단방향으로 iPhone을 매핑시켜주는것이 양방향 매핑관계가 됩니다.

 

@OneToMany

못보던 어노테션이 생겼다. @OneToMany 인데 iPhone객체를 향하여 단방향 매핑을 추가해주기 위하여 JPA에게 알려주는 어노테이션이다.

Phone은 하나이지만 iPhone은 여러가지가 들어올수 있으므로 List로 참조하였고 ArrayList로 '관례상' 초기화 해줌을 볼 수 있다.

또한 중요한것이 바로 mappedBy ,해당 값으로 무엇과 연결했는지 반대편에 phone 과 연결했다고 알려주도록하자.

 

위에서 언급한 연관관계의 주인에 대해 한번 더 정리해봅시다.

 

연관관계의 주인

객체의 양방향은 사실 단방향 관계가 2개인 것입니다. 테이블의 연관관계에서 FK가 두 테이블의 연관관계를 관리합니다. FK 하나로 어느 테이블이 어느 테이블을 조인하는 지 알 수 있습니다.

 

객체 기준의 어떤 객체를 연관관계의 주인으로 보아야 할까요? 주로 외래키가 있는 곳을 주인으로 정합니다.

 

즉 @oneToMany를 가지고 있는 쪽이 가짜 매핑이라고 볼 수 있습니다. 가짜 매핑이라고 표현한 건 주인이 아닌쪽은 읽기 기능만 합니다. 주인쪽의 객체가 등록 및 수정을 담당합니다.

 

1:n , 즉 ManyToOne에서 Many를 바라보면 연관관계가 정리가 됩니다. n쪽이 되겠네요.

 

자동차와 바퀴에서 연관관계의 주인은 ? 바퀴입니다.

 

양방향 매핑시 주의 사항

1. 무한루프

순수 객체 상태를 참조할 경우 , 양쪽 값을 모두 설정하는 일이 발생합니다. 양방향으로 매핑한다는 의미가 이런식으로 설정하기 위해 사용하기 위해 만들었을테니까요.

 

하지만 양방향 매핑을 하다보면 무한루프 에 빠지는 경우가 더러있습니다.

 

무한루프에 빠지는 케이스는 다음과 같습니다.

 

1. toString() ( + lombok)

 

2. Entity 를 Controller에서 직접 반환할 때

 

첫번째 케이스의 경우에는 toString을 사용하지 않는 것이 하나의 방편이며 두번째의 경우 단순 Data를 포함시키는 dto를 반환하는 것이 해결책이라고 볼 수 있습니다.

 

2.연관관계 편의 메서드

각 객체에 데이터를 넣어주어야할 경우 연관 관계 편의 메서드 를 생성하여 데이터를 관리할 수 있습니다.

iPhone Entity안에 연관관계편의메서드 생성

사실 set을 변형시킨 방식입니다. setter함수를 외부에 노출시키는 것은 좋은 코딩이 아니므로 명시적으로도 보기좋은 이름을 만들어 따로 관리합니다. phone이라는 객체를 iPhone 객체 안에서 따로 관리하는 방식입니다.

 

감사합니다.