다양한 연관관계 매핑
#JPA/기본
- /일대다 단방향: 객체에서 연관관계 주인은 1쪽이지만, DB에서 FK는 다쪽에 있다.
- 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조
- FK 위치와 연관관계 주인 위치가 달라서
@JoinColumn을 꼭 사용해야 함. 안쓰면 조인 테이블 생김 - FK 위치와 연관관계 주인 위치가 달라서 일쪽에서 저장 시 FK 매핑을 위한 쿼리가 추가적으로 나감 권장 X
- 다쪽에서 일쪽을 접근할 일이 없어도 다대일로 설계하는게 장점이 많다. 다대일로 설계하자.
- /일대다 양방향
- 다쪽에서 값 수정 시 FK가 업데이트 되지 않도록 억지로 읽기 전용으로 설계해야 나오는 구조.
- 공식적으로 없는 구조.
- 다대일로 설계하자.
- 주 테이블, 대상 테이블 중에 외래 키를 선택해서 둬야 하고, 외래 키에 DB 유니크 제약조건을 추가하자.
- 일대일 관계에서는 기본적으로 내 엔티티에 있는 외래키는 내가 관리한다.
- /일대일: 주 테이블에 외래 키 단방향
- 다대일(@ManyToOne) 단방향 매핑과 유사
- /일대일: 주 테이블에 외래 키 양방향
- 다대일 양방향 매핑 처럼 외래 키가 있는 곳이 연관관계의 주인.
- 반대편은 mappedBy
- /일대일: 대상 테이블에 외래 키 단방향
- 주 테이블이 아닌 대상 테이블에 FK를 두고 단방향 매핑하는 건 지원도 안되고 불가능함.
- /일대일: 대상 테이블에 외래 키 양방향
- 말에 어폐가 있는데, 사실 대상 테이블을 연관관계 주인으로 잡고 매핑을 한다.
- 일대일 주 테이블에 외래 키 양방향과 매핑 방법이 같다.
- FK 위치만 바뀐 것.
- 일대일에서 /트레이드 오프: 주 테이블과 대상 테이블 중 어디에 FK를 둘 것인가?
- 주 테이블이 연관관계 주인
- 개발자 입장: 서버 성능에 유리함(대상 테이블 데이터 유무). JPA 매핑 편리. FK에 null 허용해야 하는 단점.
- DBA 입장: FK를 옮겨야 하고, 코드 수정해야하고,… 싫어한다.
- 대상 테이블이 연관관계 주인
- DBA 입장: 주 테이블: 대상 테이블 = 1:다가 되면, 대상 테이블에 FK가 있어 대상 테이블이 주인이 되는게 유리함. (테이블 구조 변경 거의 없음)
- 개발자 입장: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨
- 테이블에는 Member에 Locker 칼럼이 없기 때문에, Member 객체의 Locker 필드에 null을 넣을지 말지 결정하기 위해서는 Locker 테이블을 뒤져야 함. 어쩔 수 없이 항상 즉시 로딩 되버림.
- 주 테이블이 연관관계 주인
- /일대일 정리
- 주 테이블에 외래 키
- 주 객체가 대상 객체의 참조를 가지는 것 처럼
주 테이블에 외래 키를 두고 대상 테이블을 찾음 - 객체지향 개발자 선호
- JPA 매핑 편리
- 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
- 단점: 값이 없으면 외래 키에 null 허용
- 주 객체가 대상 객체의 참조를 가지는 것 처럼
- 대상 테이블에 외래 키
- 대상 테이블에 외래 키가 존재
- 전통적인 데이터베이스 개발자 선호
- 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
- 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨 (프록시는 뒤에서 설명)
- 프록시 객체를 만들 때, Member에 Locker 필드가 존재하기 때문에(양방향), 결국에 Locker 필드를 뒤져야 한다.
- (Locker 필드를 뒤져야 null을 넣을지 말지를 알 수 있기 때문이다)
- 주 테이블에 외래 키
/다대다 [N:M]: 쓰지 말자.
- JPA가 중간 테이블을 만들어낸다.
- 객체에서 /다대다
- 객체는 컬렉션을 사용해서 객체 2 개로 다대다 관계 가능
- /다대다 매핑의 한계
- 편리해 보이지만 실무에서 사용X
- 연결 테이블이 단순히 연결만 하고 끝나지 않음
- /다대다 한계 극복: 연결 테이블용 엔티티를 추가해 연결테이블을 엔티티로 승격시키자.
- 실전에서는 @ManyToMany 사용X
애노테이션 속성
| 속성 | 설명 | 기본값 |
|---|---|---|
| name | 매핑할 외래 키 이름 | 필드명 + _ + 참조하는 테이블의 기본 키 컬럼명 |
| referencedColumnName | 외래 키가 참조하는 대상 테이블의 컬럼명 | 참조하는 테이블의 기본 키 컬럼명 |
| foreignKey(DDL) | 외래 키 제약조건을 직접 지정할 수 있다. 이 속성은 테이블을 생성할 때만 사용한다. | |
| unique, nullable, insertable, updatable, columnDefinition, table | @Column의 속성과 같다. |
| 속성 | 설명 | 기본값 |
|---|---|---|
| optional | false로 설정하면 연관된 엔티티가 항상 있어야 한다. | TRUE |
| fetch | 글로벌 페치 전략을 설정한다. | - @ManyToOne=FetchType.EAGER - @OneToMany=FetchType.LAZY |
| cascade | 영속성 전이 기능을 사용한다. | |
| targetEntity | 연관된 엔티티의 타입 정보를 설정한다. 이 기능은 거의 사용하지 않는다. 컬렉션을 사용해도 제네릭스로 타입 정보를 알 수 있다. 몰라도 된다 |
| 속성 | 설명 | 기본값 |
|---|---|---|
| mappedBy | 연관관계의 주인 필드를 선택한다. | |
| fetch | 글로벌 페치 전략을 설정한다. | - @ManyToOne=FetchType.EAGER - @OneToMany=FetchType.LAZY |
| cascade | 영속성 전이 기능을 사용한다. | |
| targetEntity | 연관된 엔티티의 타입 정보를 설정한다. 이 기능은 거의 사용하지 않는다. 컬렉션을 사용해도 제네릭스로 타입 정보를 알 수 있다. |
Ref) 김영한 자바 ORM 표준 JPA 프로그래밍 - 기본편
'DB Access > JPA' 카테고리의 다른 글
| [JPA] 프록시와 연관관계 관리 (0) | 2025.07.01 |
|---|---|
| [JPA] 고급 매핑 - 상속 관계 매핑 (0) | 2025.07.01 |
| [JPA] 연관관계 매핑 기초 (0) | 2025.07.01 |
| [JPA] 엔티티 매핑 (0) | 2024.11.08 |
| [JPA] 영속성 관리 (0) | 2024.11.06 |