단방향, 양방향, 연관관계 주인에 대한 설명과 예시 엔티티, 테이블은 링크 참고
연관관계 매핑 시 고려사항
- 다중성
다대일 : @ManyToOne
일대다 : @OneToMany
일대일 : @OneToOne
다대다 : @ManyToMany
=> JPA의 어노테이션은 모두 DB와 매핑위해 존재한다. 따라서 DB관점에서의 다중성을 기준으로 설정!
다대일, 일대다 등 명칭은 '대' 앞의 '다', '일' 등에 해당하는 엔티티가 테이블의 외래키를 관리한다(연관관계 주인)는 뜻
- 방향성
단방향 : 한쪽만 참조
양방향 : 양쪽 모두 참조
- 연관관계의 주인
양방향 관계의 경우 외래키가 존재하는 테이블에서의 참조를 연관관계의 주인으로 설정!
다대일 (N:1)
다대일 단방향 관계
가장 많이 사용되는 연관관계, 반대 객체는 일대다 관계
// Member 엔티티 (다대일 단방향, 양방향)
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
다대일 양방향 관계
외래키가 있는 곳을 연관관계 주인으로 설정, 양쪽을 서로 참조하게 설정
// Team 엔티티 (다대일 양방향)
@OneToMany(mappedBy = "team") // 다대일의 반대 객체는 일대다
private List<Member> members = new ArrayList<>();
일대다 (1:N)
일대다 단방향 관계
일(1)이 연관관계의 주인, 다(N)쪽에 외래키 존재 => 반대편 테이블의 외래키를 관리하므로 자주 사용하지 않음
일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자!
// Team 엔티티 (일대다 단방향, 양방향)
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<>();
// team.getMembers().add(member); 로 외래키를 update함 => update 쿼리가 추가로 날라감 (반대편 테이블 관리하므로)
일대다 양방향 관계
공식적으로는 존재하지 않는 매핑관계, @JoinColumn(insertable = false, updatable = false)를 통해서 읽기 전용으로 생성하는 것 뿐
// Member 엔티티 (일대다 양방향)
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
private Team team;
일대일 (1:1) - 주 테이블에 외래키
주 테이블 : 주로 access 하는 테이블
대상 테이블 : 주 테이블을 통해서 access 하는 테이블
일대일 단방향 관계 - 주 테이블에 외래키
다대일(@ManyToOne) 단방향 매핑과 유사함
// Member 엔티티 (일대일 단방향 - 주 테이블에 외래키)
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
일대일 양방향 관계 - 주 테이블에 외래키
외래키가 있는 곳이 연관관계의 주인, 반대편은 mappedBy 적용
// Locker 엔티티 (일대일 양방향 - 주 테이블에 외래키)
@OneToOne(mappedBy = "locker")
private Member member;
일대일 (1:1) - 대상 테이블에 외래키
일대일 단방향 관계 - 대상 테이블에 외래키
JPA에서 지원하지 않음
일대일 양방향 관계 - 대상 테이블에 외래키
주 테이블에 외래키에서의 방법과 동일
다대다 (N:M)
관계형 데이터 베이스는 정규화된 테이블 2개로 다대다 관계를 풀어낼 수 없음
따라서 중간에 테이블을 추가하여 일대다, 다대일 관계로 풀어내야 함
다대다 단방향 , 양방향 관계
@JoinTable(name = "중간 테이블 이름") 을 통해서 중간의 연결 테이블을 지정
// Member 엔티티 (다대다 단방향, 양방향)
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT")
private List<Product> products = new ArrayList<>();
// Product 엔티티 (다대다 양방향)
@ManyToMany(mappedBy = "products")
private List<Member> members = new ArrayList<>();
다대다 = 일대다 + 다대일 로 풀어내기
연결 테이블에 다른 속성이 추가되는 경우가 다반사이다. 예를 들면 주문시간, 수량과 같은 값들이 추가될 수 있다.
다대다에서 사용된 연결 테이블을 연결 엔티티로 승격하여 새로운 클래스를 생성한다.
@ManyToMany = @OneToMany + @ManyToOne
// Member 엔티티
@OneToMany(mappedBy = "member") // Member 입장에서는 일대다
private List<MemberProduct> mwemberProducts = new ArrayList<>();
// MemberProduct 엔티티
@ManyToOne // MemberProduct 입장에서는 다대일
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne // MemberProduct 입장에서는 다대일
@JoinColumn(name = "PRODUCT_ID")
private Product product;
// Product 엔티티
@OneToMany(mappedBy = "product") // Product 입장에서는 일대다
private List<MemberProduct> memberProducts = new ArrayList<>();
'Spring Boot > JPA' 카테고리의 다른 글
[JPA] 즉시로딩, 지연로딩 (0) | 2023.12.28 |
---|---|
[JPA] 연관관계 매핑 - 상속관계 매핑, @MappedSuperclass (1) | 2023.12.18 |
[JPA] 연관관계 매핑 - 단방향 매핑, 양방향 매핑 (1) | 2023.12.18 |
[JPA] 엔티티 매핑 관련 annotation 정리 (0) | 2023.12.14 |
[JPA] 영속성 컨텍스트, 엔티티 매니저 CRUD (0) | 2023.12.13 |