티스토리 뷰
1. Entity간의 연관관계(방향) 이란?
DB에서는 관계를 맺어주기만 하면 양방향 참조가 가능하다.
하지만 객체(Entity)간의 클래스는 참조방향을 지정해줘야 한다.
어떤 방향성을 고려해야하는건 굉장히 중요하다.
2. 방향을 가져야하는 이유
객체지향적인 관점에서 A클래스와 B클래스가 연관관계일때, A클래스는 B클래스를
사용하게되고 이런 경우에 방향성을 갖게 된다.
하지만 방향성을 남발하면 성능에 문제가 갈 수 있다.
예시로, 게시판을 구현하고 한 명의 사용자가 수십개의 게시판의 글을 작성했고, 회원클래스가
게시판클래스의 방향을 갖는 경우 회원의 게시판을 불러 오면 DB에 무리가 갈 수 있다.
(그래서 다른 방법으로 Repository 페이징 기능을 구현한다.)
그래서 가능한 단방향으로 구현 → 양방향이 필요한 경우에 성능과 편의성으로 고려해서 구현할 수 있다.
3. 양방향 연관관계의 주인
두 개의 Entity클래스가 서로를 참조하고 있을 때, ‘연관관계의 주인’을 정해야 한다.
양방향으로 참조가 되어있을 때 양쪽에서 값을 갱신하게 되면 데이터간의 충돌이 일어날 수 있다.
그래서 연관관계 주인만이 외래키를 관리하여 등록, 수정, 삭제 등을 할 수 있고, 반대편은 읽기만
가능하다. (주인이 아닌 쪽에서 갱신을 시도해봤자 DB에 반영이 안된다.)
4. 연관관계(방향) 설정하기
엔티티의 연관관계를 매핑할 때는 3가지를 고려해야한다.
- 다중성
- 단방향, 양방향
- 연관관계의 주인
일, 다 관계에선 다가 무조건 주인으로 설정한다.
따라서 객체간의 관계에서 연관관계의 주인은 항상 다쪽이다.
가장 많이 쓰이는 다대일을 예시로 들고 마치도록 하겠다.
@Entity
public class A {
. . .
@ManyToOne
@JoinColumn(name = "b_id")
private B b;
}
@Entity
public class B {
. . .
//연관관계의 주인은 A클래스
@OneToMany(mappedBy = "b")
private Set<A> a;
}
양방향 참조를 하게 되면 객체는 변경할 곳이 2곳이지만
테이블은 한 곳, 즉 FK쪽만 바꾸면 되기 때문에 두 곳중 하나를 주인으로 정해줘야 한다. -> 연관관계 주인
쉽게 말해서 mappedBy라는 옵션을 설정한 쪽이 주인이 아니다.
mappedBy란 ?
위 코드로 예시를 들겠다. mappedBy = "b"를 해석하면, B테이블에 있는 b필드에 의해서 매핑된 거울이라는 뜻이다. (거울 == 읽기전용)
앞에서 말했지만 읽기 전용이 되면 값을 바꿔도 데이터베이스에 반영되지 않는다.
그리고 필수로 알아둬야 할 것이 있다.
바로 XtoOne한테 fetchType을 LAZY(지연로딩)으로 바꿔주는 것이다. (XtoOne == ManyToOne, OneToOne)
기본적으로 ManyToOne, OneToOne의 fetchType 디폴트값은 EAGER(즉시로딩)이다.
EAGER(즉시로딩) 을 쓰면 안되는 이유 ?
1. 예측이 어렵고 어떤 SQL이 실행될지 추적하기 어렵다.
2. 특히 JPQL을 실행할 떄 N + 1문제가 자주 발생한다.
결론: XtoOne의 fetchType은 지연로딩(LAZY)으로 바꾸자
만약 트랜잭션 문제로 LAZY에 문제가 생기면 ? "궁극의 패치조인"을 사용하자.
쓰면 안되는 것 정리
김영한: ManyToMany, OneToOne, 그리고 fetchType=EAGER(즉시로딩)을 지양하자.
'JPA' 카테고리의 다른 글
패러다임의 불일치 (0) | 2022.07.18 |
---|---|
JPA가 생겨난 이유 (0) | 2022.07.09 |
객체에서 IDENTITY 전략으로 쉽게 기본 키 매핑 (0) | 2022.04.05 |
영속성 컨텍스트 개념과 원리 (0) | 2022.04.04 |
엔티티와 테이블 매핑 (0) | 2022.04.04 |
- Total
- Today
- Yesterday