본문으로 바로가기
728x90

 

먼저 들어가기 전 테이블과 객체의 매핑 차이점을 알고 들어가야 한다.


테이블

- 외래키 하나로 양쪽 참조 가능 (조인)

- 사실 방향이라는 개념이 없음

 

객체

- 참조용 필드가 있는 쪽으로만 참조 가능

- 한쪽만 참조하면 단방향 매핑

- 양쪽이 서로 참조하면 양방향 매핑

 

이제부터는 외래키를 관리하는 테이블을 연관관계 주인이라고 하겠다.

주인의 반대편에서는 외래키에 영향을 주지않고 조회만 가능

 

다대일 [N:1]

 - 관계형 DB에서는 다 쪽이 항상 연관관계 주인, 즉 외래키를 관리

따라서, 다 쪽에 외래키를 생성하는 것이 DB와의 관계를 고려하여 설계하는데 적합하다.

 

Example) Member와 Team이 N:1의 관계를 가지고 있다고 가정하자.

 

Member에서 Team으로의 단방향 매핑일 때

- 다(Member) 쪽의 엔티티에 @ManyToOne 선언

- @JoinColumn을 통해 연관관계를 맺고 있는 외래키의 이름을 정해준다.

- 연관관계를 맺고 있는 Team의 객체를 생성한다.

 

- DB 테이블상에 위와 같이 TEAM_ID라는 외래키가 추가되었다.

 

Member와 Team이 양방향 매핑일 때

- 일(Team) 쪽의 엔티티에 @OneToMany 추가

- mappedBy 속성을 통해 Member와 관계를 맺고 있는 객체의 이름을 적어준다.

- 여러개의 객체가 필요하므로 컬렉션을 통해 Member의 객체를 생성한다.

 

일대다 [1:N]

- 위와 반대로 일 쪽에 외래키를 관리하는 경우이다.

 

Team에서 Member으로의 단방향 매핑일 때

- Team 엔티티가 외래키를 관리하므로, Team 테이블에 @JoinColumn의 속성을 적어준다.

 

Team과 Member가 양방향 매핑일 때

- 다(Member)쪽에 객체를 추가 후,

- mappedBy가 아닌 @JoinColumn을 작성해주어야 양방향 관계를 유지할 수 있다.

- 다만 이와 같이 작성하면 어디가 연관관계 주인인지 알기 어려우므로, insertable=false, updatable=false 속성을 넣어주어 읽기 전용으로 변환시켜주어야 한다.

 

-> 이와 같이 작성하는 것은 복잡하므로 다대일[N:1] 양방향 매핑을 권장

 

일대일 [1:1]

- 두 개의 테이블 중 하나를 연관관계의 주인으로 선택 (이왕이면, 자주 쓰이는 테이블로 쓰기)

 

EXAMPLE) Member와 LOCKER를 일대일 매핑이라 하고, Member를 주 테이블로 설정할 때

 

단방향 매핑일 때

- Member 테이블에 @OneToOne 선언

- @JoinColumn으로 외래키 컬럼 이름 생성

- Locker의 객체 생성

 

 

양방향 매핑일 때

- Locker 테이블에 @OneToOne 추가

- mappedBy 속성을 통해 Member와의 관계를 맺고있는 Locker의 객체 선언 

 

다대다 [N:M]

- 관계형 DB는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없음
- 연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야함
- 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계 가능
- 위와의 간극을 줄이기 위해 연결테이블용 엔티티 추가

(@ManyToMany-> @ManyToOne, @OneToMany)로 풀어서 설정

 

EXAMPLE) Member와 Product가 N:M 매핑일 때

 

둘간의 연결 테이블인 MemberProduct 생성

- @ManyToOne을 통해 다 쪽에 @JoinColumn 선언 후,

Member와 Product의 객체 생성

 

- @OneToMany를 선언 후,

- mappedBy를 통해 자신과 관계를 맺고 있는 테이블의 객체를 선언

- 다대다 관계는 실제로, 연결 테이블에 수 많은 데이터가 들어가게 되어 더욱 복잡해질 수 있으므로

실무에서는 추천하지 않는 방법이다.

 

 

출처 : ORM 표준 JPA 프로그래밍

728x90