JPA 연관관계 매핑 - 다중성

Growing_HJ·2024년 7월 30일

JPA

목록 보기
7/15

연관관계에 존재하는 다중성의 종류

  1. 다대일 (@ManyToOne) - 단방향 & 양방향
  2. 일대다 (@OneToMany) - 단방향 & 양방향
  3. 일대일 (@OneToOne) - 주 테이블 단방향 & 양방향
    3-1. 일대일 (@OneToOne) - 대상 테이블 단방향 & 양방향
  4. 다대다 (@ManyToMany) - 단방향 & 양방향
    +참고 ) 다중성은 왼쪽을 연관관계의 주인으로 정했다. 다대일 양방향일 경우, 다가 연관관계의 주인이다.
    연관관계의 매핑시 고려해야 할 사항
  5. 다중성
  6. 단방향, 양방향
  7. 연관관계의 주인 - 연관관계의 주인은 mappedby(다쪽) 을 사용하지 않는다.

A. 다대일 단방향 [ N:1 ] - @ManyToOne



회원은 Member.team 으로 팀 엔터티를 참조할 수 있지만, 반대로 팀에는 회원을 참조하는 필드가 없다. -> 회원과 팀은 다대일 단방향 연관관계

@ManyToOne 
@JoinColumn(name = "TEAM_ID)
private Team team;

-> @JoinColumn(name = "TEAM_ID) 를 사용해서 Member.team 필드를 TEAM_ID 외래 키와 매핑했다.
=> Member.team 필드로 회원 테이블의 TEAM_ID 외래키를 관리한다.

  • 다대일 관계의 반대 방향은 항상 일대다 관계.
    - 🌟 데이터베이스 테이블의 일(1), 다(N) 관계에서 외래 키는 항상 N (다) 쪽에 있다 🌟.
    따라서, 객체 양방향 관계에서 연관관계의 주인은 항상 다쪽이다.
    => 📌 mappedBy를 사용하지 않는다 📌

A-1. 다대일 양방향 [ N:1, 1:N ] - @ManyToOne

  • 다대일 양방향의 객체 연관관계에서 실선이 연관관계의 주인(Member.team) 이고,
    점선 (Team.members) 은 연관관계의 주인이 아니다.


    📌 양방향은 외래 키가 있는 쪽이 연관관계의 주인이다. 📌
    - 일대다와 다대일 연관관계는 항상 다(N) 에 외래 키가 존재.
    위의 코드에서는 다 쪽인 MEMBER 테이블이 외래 키를 가지고 있으므로
    Member.team 이 연관관계의 주인이다.
    📌 양방향 연관관계는 항상 서로를 참조해야 한다. 📌
    - 양방향 연관관계에서 어느 한쪽만 참조하면 양방향 연관관계가 성립하지 않는다.
    항상 서로를 참조하게 하려면 연관관계 편의 메소드를 작성하는 것이 좋다.
    member 테이블의 setTeam 메소드 / Team 테이블의 addMember 메소드


B. 일대다 단방향 [ N:1 ] - @OneToMany

일대다 관계는 다대일 관계의 반대 방향.

일대다 관계는 Entity 를 하나 이상 참조할 수 있으므로,
자바의 컬렉션인 Collection,List, Set, Map 중에 하나를 사용해야 한다. 

일대다 관계의 예시 ) 하나의 팀은 여러 회원을 참조할 수 있는 관계,
일대다 단방향 관계의 예시 ) 팀은 회원들을 참조하지만 반대로 회원은 팀을 참조하지 않는 관계


  • 일대다 단방향 관계를 매핑할 경우에는 @JoinColumn 을 명시해야 한다.
    📌 일대다 단방향 매핑의 단점
  • 매핑한 객체가 관리하는 외래 키가 다른 테이블에 있다는 것.

    일대다 단방향 매핑 VS 다대일 양방향 매핑
    일대다 단방향 매핑을 사용할 경우,
    엔터티를 매핑한 테이블이 아닌 다른 테이블의 외래 키를 관리해야 함.
    다대일 양방향 매핑의 경우, 관리해야 하는 외래 키가 본인 테이블에 있다. 따라서
    일대다 단방향 매핑 같은 문제가 발생하지 않는다.


B-1 . 일대다 양방향 [ 1:N , N:1 ] - @OneToMany

양방향 매핑에서 @OneToMany 는 연관관계의 주인이 될 수 없다.

관계형 데이터베이스의 특성상 일대다, 다대일 관계는 항상 다 쪽에 외래 키가 존재한다. 
따라서, @OneToMany, @ManyToOne 둘 중에 연관관계의 주인은 항상 다 쪽인 
@ManyToOne 을 사용한 곳이다. 

=> 📌 @ManyToOne 에 mappedBy 속성이 없는 이유

일대다 양방향 매핑 방법

  • 일대다 단방향 매핑 반대편에 같은 외래 키를 사용하는 다대일 단방향 매핑을 읽기 전용으로 하나 추가하면 됨.

  • 위의 코드에서는 일대다 단방향 매핑 반대편에 다대일 단방향 매핑을 추가한 것.
    이때 일대다 단방향 매핑과 같은 TEAM_ID 외래키 컬럼을 매핑한 것.
    insertable = false & updateable = false : 읽기만 가능하게 설정.

C. 일대일 [ 1 : 1 ] - @OneToOne

일대일 관계는 양쪽이 서로 하나의 관계만을 가진다 .
📌 일대일 관계의 특징
1. 일대일 관계는 그 반대도 일대일 관계임.
2. 테이블 관계에서 일대다 , 다대일은 항상 다 (N) 쪽이 외래 키를 가진다.
🌟 반면에 일대일 관계는 주 테이블이나 대상 테이블 둘 중 어느 곳이나 외래 키를 가질 수 있다.🌟

1. 주 테이블에 외래키 두기

  • 주 객체가 대상 객체를 참조하는 것 처럼 주 테이블에 외래 키를 두고 대상 테이블을 참조한다. 외래 키를 객체 참조와 비슷하게 사용할 수 있다.
    + 장점 ) 주 테이블이 외래 키를 가지고 있으므로 주 테이블만 확인해도 대상 테이블과 연관관계가 있는지 알 수 있다.

2. 대상 테이블에 외래키 두기

  • 대상 테이블에 외래키를 두는 방법의 장점은 테이블 관계에서 일대일로 변경할 때 테이블 구조를 그대로 유지할 수 있다.

C - 1 .일대일 관계 , 주 테이블에 외래키 두기 - 단방향

1. 일대일 단방향 - 주 테이블에 외래키 두기

  • 일대일 관계 이기 때문에 @OneToOne 어노테이션 사용.

C - 2 .일대일 관계 , 주 테이블에 외래키 두기 - 양방향

2. 일대일 양방향 - 주 테이블에 외래키 두기


C - 3 .일대일 관계 , 대상 테이블에 외래키 두기 - 단방향 & 양방향

  • 일대일 매핑에서 대상 테이블에 외래 키를 두고 싶으면 윙화 같이 양방향으로 매핑한다. 주 엔티티인 Member 엔터티 대신에 대상 엔터티인 Locker 를 연관관계의 주인으로 만들어서 LOCKER 테이블의 외래키로 관리하도록 하였다.

D. 다대다 관계 [ N : N ] - @ManyToMany

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

다대다 단방향 관계

  • 회원 entity 와 상품 entity 를 @ManyToMany 로 매핑했다.
    위의 코드는 @ManyToMany 와 @JoinTable 을 사용해서 연결 테이블을 바로 매핑한 것.
  • @ManyToMany사용시 연결 테이블을 자동으로 처리해주므로 모델이 단순해지고 여러가지로 편리하다.
  • 회원과 상품을 연결하는 회원_상품(Member_Product) 엔터티 없이 매핑을 완료할 수 있다.
+ @JoinTalbe 의 속성
1. @JoinTable.name : 연결 테이블을 지정. 
2. @JoinTable.joinColumns : 현재 방향인 회원과 매핑할 조인 칼럼 정보를 지정.
3. @JoinTable.inverseJoinColumns : 반대 방향인 상품과 매핑할 조인 컬럼 정보
   를 지정 

+ 복합 기본 키

회원 상품 엔티티 기본 키가 MEMBER_ID 와 PRODUCT_ID 로 이루어진 복합 기본 키다. JPA 에서 복합키 사용시, 별도의 식별자 클래스를 생성해야한다. 그리고 엔터티에 @IdClass 를 사용해서 식별자 클래스를 지정하면 된다.

  • 다대다 양방향 연관관계 설정하기
@Entity 
public class Product {
	@Id
    private String id;
    @ManyToMany (mappedBy = "products") // 역방향 추가
    private List<Member>members;
}

복합 키를 위한 식별자 클래스의 특징

public class MemberProducted implements Serializable {
	private String member;
    private String product;
    @Override 
    public boolean equals(Object o) {...}
    @Override 
    public int hashCode() {...}
}
  1. 복합 키는 별도의 식별자 클래스로 만들어야 한다.
  2. Serializable 을 구현해야 한다.
  3. equals 와 hashCode 메소드를 구현해야 한다.
  4. 기본 생성자가 있어야 한다.
  5. 식별자 클래스는 Public 이어야 한다.
  6. @IdClass 를 사용하는 방법 외에 @EmbeddedId 를 사용하는 방법도 있다.

+ 식별 관계 & 비식별 관계

식별 관계 : 받아온 식별자를 기본 키 + 외래 키로 사용한다.
비식별 관계 : 받아온 식별자는 외래 키로만 사용하고 새로운 식별자를 추가한다.

0개의 댓글