JAVA

[JAVA] JPA 다양한 연관관계 매핑

응디 2021. 12. 9. 13:43

연관관계 매핑 시 고려사항 3가지

  1. 다중성 : 일대일, 일대다, 다대일, 다대다
  2. 단방향, 양방향
  3. 연관관계 주인

다중성

※ 보통 일대다, 다대일 이런 경우 맨 앞에 있는 애가 연관관계 주인이다.

 

1. 다대일

외래키는 항상 다대일 중 '다' 쪽에 존재한다. 따라서 객체 양방향 관계에서 연관관계의 주인은 항상 '다' 쪽이다.

단방향 예시
양방향 예시

양방향에서 '다' 쪽인 Member테이블이 Team 에 관한 외래키를 가지고 있으므로 연관관계의 주인이다.


2. 일대다

다대일 관계의 반대방향이다. 일대다에서는 엔티티를 하나 이상 참조 가능하므로 Collection, List, Map 중 하나 사용해야 한다. (실무에서 잘 사용하지 않는다.)

'일' 이 연관관계의 주인이다.

 

2-1. 단방향

  • 하나의 팀은 여러 회원을 참조 할 수 있다. (팀은 회원을 참조하지만 회원은 팀을 참조하지 않음)
  • JoinColumn을 꼭 사용해야 한다. 그렇지 않으면 조인 테이블 방식(중간에 테이블을 하나 삽입하는 방식)을 사용
  • 엔티티가 관리하는 외래키가 다른 테이블에 있음( 어마어마한 단점 )
  • 연관관계 관리를 위해 추가로 UPDATE SQL 을 실행함 ( 성능 저하 )
  • 일대다 단방향 매핑보다는 다대일 양방향을 사용하자!

2-2. 양방향

  • 사실 이런 매핑은 공식적으로 존재하지 않음
  • @JoinColumn(insertable=false, updatable=false) 사용
  • 읽기전용 필드를 사용해서 양방향으로 사용
  • 마찬가지로 다대일 양방향을 사용하는걸 권장!

3. 일대일

일대일 관계는 그 반대도 일대일 관계이다.

주테이블이나 대상테이블 아무 곳에 외래 키 선택해서 삽입가능하다.

외래 키 데이터베이스에 유니크 제약조건을 추가 해줘야한다.

다대일 단방향과 비슷함

 

3-1. 주테이블에 외래키가 존재 할 경우

객체 지향 개발자들은 주 테이블에 외래 키가 있는 것을 선호하며, JPA도 주 테이블에 외래 키가 있으면 좀 더 편하게 매핑이 가능 하다!

 

장점 : 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능하다.

단점 : 값이 없으면 외래키에도 null값을 허용함

 

  • 단방향

// JoinColumn은 이름을 지정해주는게 좋음 -> 지정안하면 랜덤으로 들어가서 복잡해짐
@OneToOne
@JoinColumn(name = "LOCKER_ID") 
private Locker locker;  // 일대일 관계 완료

 

  • 양방향 → 연관관계 주인을 정해야 함

위의 경우 Member 테이블이 외래키를 가지고 있으므로 Member.locker가 연관관계의 주인이다. 따라서 반대인 사물함의 Locker.member는 mappedBy를 선언해서 연관관계의 주인이 아니라고 설정해줘야한다.

다대일 양방향 매핑 처럼 외래키가 있는 곳이 연관 관계의 주인이 되고, 반대편은 mappedBy 적용
/* Member.java */
@OneToOne
@JoinColumn(name = "LOCKER_ID") 
private Locker locker;  // 일대일 관계 완료

/* Locker.java */
@OneToOne(mappedBy = "locker")
private Member member;  // 읽기전용

 

3-2. 대상 테이블에 외래키가 존재 할 경우

전통적인 DB 개발자들이 선호한다.

 

장점 : 주 테이블과 일대일에서 일대다로 관계 변경 시 테이블 구조가 변하지 않음

단점 : 프록시 기능의 한계로 지연 로딩으로 설정해도 즉시 로딩 됨

 

  • 단방향

위 그림 처럼 일대일 관계 중 대상 테이블에 외래 키가 있는 단방향 관계는 JPA에서 지원하지 않는다.

따라서 이런 경우 단방향 관계를 Locker에서 Member 쪽으로 수정하거나 양방향 관계로 만들고 Locker를 연관관계 주인으로 설정해야 한다.

 

  • 양방향

일대일 관계에서 대상 테이블에 외래키를 두고 싶으면 위 예시 처럼 양방향으로 매핑해야한다.

 


4. 다대다

★ 다대다는 실무에서 쓰지 않는게 좋다.

  • 관계형 데이터 베이스는 정규화된 테이블 2개로 다대다를 표현 할 수 없다.
  • 일대다, 다대일 관계로 풀어내는 연결 테이블을 사용한다.
  • @ManyToMany를 사용한다.

※ 다대다 매핑의 한계

편리해 보이지만 실무에서 사용하기엔 한계가 있다.

보통 회원이 상품을 주문하면 연결 테이블에 단순히 Member_id 와 Product_id만 담고 끝이 아니라 주문 수량, 주문 날짜 등 다른 컬럼이 사용되기 때문에 위처럼 외래키값을 제외한 다른 컬럼을 추가해주면 더이상 @ManyToMany 사용이 불가하다.

→ 추가한 컬럼을 매핑 할 수 없기 때문에!

 

 

※ 다대다 매핑의 한계 극복

연결 테이블용 엔티티를 추가해줌(연결 테이블을 엔티티로 바꿔준다.)

@ManyToMany 대신 @OneToMany, @ManyToOne 를 사용한다.

  

'JAVA' 카테고리의 다른 글

[JAVA] @MappedSuperclass  (0) 2022.01.04
[JAVA] JPA 고급 매핑 (상속 관계 매핑)  (0) 2021.12.16
[JAVA] JPA 연관관계 매핑( 양방향 )  (0) 2021.11.17
[JAVA] JPA 연관관계 매핑( 단방향 )  (0) 2021.11.16
[JAVA] JPA 기본키 매핑  (0) 2021.11.11