객체와 관계형 DB가 지향하는 패러다임의 차이를 극복하는 방법.
✍연관관계 매핑
- 🌹 객체의 참조와 테이블의 외래 키를 매핑
- 🔮 객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다.
- 테이블에 맞추어 모델링을 하면, 코드를 객체 지향스럽게 짤 수 없음.
=> 외래 키에 대한 참조가 있어야하는데, 테이블에 맞추어 설계하면 객체가 외래 키 식별자 값을 그대로 갖게 됨.
=> 따라서 다른 테이블에 접근할 때 외래 키 식별자로 계속 DB에 접근해야 한다.
테이블은 외래 키로 조인을 사용하여 연관된 테이블을 찾음 <=> 객체는 참조를 사용해서 연관된 객체를 찾음.
ㆍ단방향 연관관계
@ManyToOne
- 해당 Entity에서 다른 entity에 접근하기 위한 참조의 개념으로, N : 1 의 관계를 설정할 때 사용. 'N'을 담당하는 테이블
- N쪽이 연관관계의 주인이 되면 깔끔한 설계가 가능하다.
@OneToMany
- 해당 Entity에서 다른 entity에 접근하기 위한 참조의 개념으로, 1 : N 의 관계를 설정할 때 사용. '1' 을 담당하는 테이블
@OneToOne
- 1:1 관계를 설정할 때 사용.
@ManyToMany
- N:N 관계를 설정할 때 사용.
@JoinColumn (name = "테이블의 FK")
- 해당 관계에서 Join하는 컬럼을 정의.
ㆍ양방향 연관관계 & 연관관계의 주인
- 단방향, 양방향의 테이블 연관관계는 같다. 테이블은 기본적으로 방향이라는 게 없음. FK로 Join 하면 양방향이 되기 때문.
ㆍ 양방향 매핑 - 반대 방향으로 객체 그래프 탐색.
- 다만, 객체에서는 FK개념이 없기때문에, 다른 객체를 참조하기 위한 필드가 필요.
mappedBy
- 주인을 지정하는 속성
- 해당 속성이 사용된 관계는 set 을 할 수 없다.
💡❓ 객체와 테이블이 관계를 맺는 차이.
- 객체 : Member -> Team & Team -> Member = 단방향 2개 (객체의 관계는 양방향 X, 단방향 관계 2개)
- 테이블 : Member <-> Team = 양방향 1개 (외래 키 하나로 두 테이블의 연관관계를 관리한다.)
- 테이블은 FK 하나로 연관관계를 설정할 수 있다. 하지만, 객체는 두 Entity 각각의 관계를 이용하여 서로 다른 객체를 참조하므로, 둘 중 하나로 외래 키를 관리해야 한다. (연관관계의 주인)
연관관계의 주인
- 연관관계의 주인만이 외래키를 등록, 수정 한다.
- 주인이 아닌 쪽은 읽기만 가능하다. (mappedBy 속성 사용하여 주인을 지정.)
- 주인이 아닌 쪽의 필드는 DB 테이블에 영향이 가지 않는다. 단지, 매핑된 객체를 참조하기 위한 필드일 뿐.
- 외래 키가 있는 곳을 주인으로 정하자. => 외래키의 반대 편을 주인으로 정하면 주인의 필드가 바뀌었을 때 다른 테이블에 쿼리가 나간다. 성능 이슈도 존재.
- 관계에서 'N'쪽에 있는 (@ManyToOne) Entity를 연관관계의 주인으로 정하자.
양방향 매핑시 주의점❓❗❕
- 연관관계의 주인에 값을 입력하지 않음. mappedBy로 매핑된 주인에게 값을 넣어주었는지 확인하자. DB관점에서는 주인에만 값을 넣어주면 되지만, 객체 상태를 고려하면 양쪽 다 값을 넣어주는 것이 맞다. (테스트 케이스 작성, 객체 상태를 고려하여(flush()는 예외)) 따라서, 양쪽 다 값을 넣어주게 끔 연관관계를 설정해주는 메소드를 작성하자. 이 메소드는 한 쪽에만 정의하는 것을 추천.
- 무한 루프를 조심하자. (toString(), lombok, JSON생성 라이브러리 .. 등에서 양쪽 Entity를 참조하려 할 때) => StackOverflowError 발생.
=> Entity를 컨트롤러에서 그대로 반환하는 것이 아닌, Dto(값만 있는 객체)로 변환해서 반환하는 것을 추천.
- 기본적으로 단방향 매핑만으로 연관관계 매핑을 끝내놓고, 실제 애플리케이션 개발 단계에서 양방향 매핑을 고려하자. (객체 설계 시 양방향 매핑이 그리 좋지 않다.)
- 설계 단계에서 핵심 관심사에 따라 필요한 것만 남겨, 관계를 끊어내는 것이 중요하다.
본 게시글은 김영한님의 Inflearn 강의를 토대로 제작되었습니다.
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard