🌱 SPRING/JPA

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

1HOON 2020. 7. 19. 16:56

 

연관관계 매핑 시 고려사항


  • 다중성
  • 단방향 or 양방향
  • 연관관계의 주인

 

다중성

  • N:1 → @ManyToOne
  • 1:N → @OneToMany
  • 1:1 → @OneToOne
  • N:M → @ManyToMany

 

단방향 or 양방향

  • 테이블
    • 외래 키 하나로 양쪽 JOIN 가능
    • 사실 방향이라는 개념은 없다.
  • 객체
    • 참조용 필드가 있는 쪽으로만 참조 가능
    • 한쪽만 참조하면 단방향
    • 양쪽이 서로 참조하면 양방향

 

연관관계의 주인

  • 테이블은 외래 키 하나로 두 테이블이 연관관계를 맺는다.
  • 객체의 양방향 관계는 참조가 각각 존재하므로, 둘 중 테이블의 외래 키를 관리할 객체를 지정해야한다.
  • 연관관계의 주인 → 외래 키를 관리하는 참조
  • 주인의 반대편 → 외래 키에 영향을 주지 않고, 단순 조회만 가능함.

 

 

다대일 N:1


 

  • 가장 많이 사용하는 연관관계이다.
  • @ManyToOne
  • 1
    2
    3
    4
    5
    6
    7
    8
    @Entity
    public class Member
    {
        ...
     
        @ManyToOne
        private Team team;
    }
    cs

 

다대일의 양방향

  • 외래 키가 있는 쪽이 연관관계의 주인이다.
  • 양쪽을 서로 참조하도록 개발한다.
  • 연관관계 편의 메서드를 사용하자.

 

 

일대다 1:N


 

  • 일대다 단뱡향에서는 일(1)이 연관관계의 주인이다.
  • 테이블의 일대다 관계는 항상 다(N) 쪽에 외래 키가 있다.
  • 하지만 객체이므로 반대편 테이블의 외래 키를 관리하게된다.
  • @JoinColumn을 꼭 사용해야한다. @JoinColumn을 사용하지 않으면 두 테이블간의 조인 테이블을 생성하는 방식이 사용된다.
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Entity
    public class Member
    {
        ...
     
        @ManyToOne
        @JoinColumn(name = "TEAM_ID")
        private Team team;
    }
     
    @Entity
    public class Team
    {
        ...
        @OneToMany
        private List<Member> members = new ArrayList();
    }
    cs
  • 단점
    • 엔티티가 관리하는 외래 키가 다른 테이블에 있다.
    • 연관관계 관리를 위해 추가로 UPDATE를 실행한다.

 

일대다의 양방향

  • 좋은 방법은 아니다. 이렇게 할바에는 다대일 양방향을 사용하자.
  • 연관관계의 주인인 Member의 team 필드를 읽기 전용 필드로 만들어 사용하고, 실제 값 입력은 Team의 members를 이용해 처리한다.
  • 읽기 전용 필드는 @JoinColumn 어노테이션의 insertable, updatable 속성을 false로 지정한다.
  • 1
    2
    3
    4
    5
    6
    7
    8
    @Entity
    public class Member
    {
        ...
        @ManyToOne
        @JoinColumn(insertable=false, updatable=false)
        Team team;
    }
    cs

 

 

일대일 1:1


  • 일대일 관계이므로 외래 키가 존재하는 테이블을 자유롭게 선택할 수 있다.
  • 외래 키에 UNIQUE 제약조건을 추가한다.
  • @OneToOne
  • 1
    2
    3
    4
    5
    6
    7
    8
    @Entity
    public class Member
    {
        ...
        @OneToOne
        @JoinColumn(name="LOCKER_ID")
        Locker locker;
    }
    cs

 

일대일의 양방향

  • 외래 키가 존재하는 곳이 연관관계의 주인이다.
  • 연관관계의 주인이 아닌쪽에 mappedBy 를 적용해주자.

주 테이블에 외래키 방식
대상 테이블에 외래키 방식

주 테이블에 외래키 방식 대상 테이블에 외래키 방식
- 객제지향 개발자 선호
- JPA 매핑 편리
- 장점 : 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
- 단점 : 값이 없으면 외래 키에 NULL 허용
- 전통적인 데이터베이스 개발자 선호
- 장점 : 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지 가능
- 단점 : 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨

 

 

다대다 N:M


  • 객체에서는 이 관계가 표현 가능하지만, RDBMS에서는 불가능함. → 두 테이블간 연결 테이블을 추가해 1:N:1 관계로 만들어야한다.

  • @ManyToMany
  • @JoinTable로 연결 테이블을 지정한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Entity
public class Member
{
    ...
    @ManyToMany(mappedBy = "members")
    List<Produt> products = new ArrayList();
}
 
 
@Entity
public class Product
{
    ...
    @ManyToMany
    @JoinTable(name = "MEMBER_PRODUCT", joinColumns = @JoinColumn(name = "PRODUCT_ID"), inverseJoinColumns = @JoinColumn(name = "MEMBER_ID"))
    List<Member> members = new ArrayList();
}
cs

 

  • 편리해보이지만, 두 테이블관의 연결 정보가 추가될 수도 있기 때문에 보통 N:M 대신 1:N:1 관계를 사용한다.

 

 


출처 :: 인프런 강의(자바 ORM 표준 JPA 프로그래밍 - 기본편)

반응형