본문 바로가기

백엔드 개발/JPA

JPA의 핵심 : '연관관계' 정리

JPA란?

 

JPA : 객체 - ERD 매핑에 있어 발생하는 패러다임 불일치 해결을 위해서 사용

 

연관 관계

 

연관 관계 : 개발자가 선택하는 관계 설정법으로, 비즈니스 로직, 요구사항에 따라서 그때그때 더 적절한 관계를 고른다 

  • 연관관계 정의 규칙 3가지
    • 방향 : 단방향 OR 양방향
    • 연관관계의 주인 : WHEN 양방향 -> 연관관계에서 관리 주체가 되는 쪽
    • 다중성 : 다대일(多 : 1) , 일대다(1 : 多) , 일대일(1 : 1) , 다대다 (多 : 多)
연관관계 정의 규칙 中 1번째 - 방향
단방향
양방향

 

- DB 테이블 : 외래키(FK) 1개를 가지고 양쪽에 있는 테이블을 조인(JOIN)이 가능하다. 그래서 DB 자체는 양방향, 단방향을 굳이 따지지 않는다

 

하지만 HOWEVER!!!!!!!!!

 

- 객체 : 참조용 필드가 있는 객체만 다른 객체를 참조하는 것이 가능함 (이제부터 방향이 중요해짐)

두 객체 사이에 

  • 한 객체만 참조용 필드를 가지고 참조하는 경우 : 단방향 관계 (← OR )
  • 두 객체 모두 참조용 필드를 가지고 참조하는 경우 : 양방향 관계 ( & ← )

그래서 SO!!!!

JPA 이용해서 DB와 객체가 패러다임을 맞추기 위해서는, 객체는 단방향 연관 관계를 가질지 OR 양방향 연관 관계를 가질지 선택해야한다. (인생은 다... 선택의 연속이다... 객체콜리 너마저....)

↳ Q. 어떻게 선택하나? 

A. 비즈니스 로직, 요구사항에 따라 선택하게 된다.

ex. Board.getPost() , Post.getBoard()로 두 객체가 서로를 단방향 참조했다면, 
결론적으로 양방향 연관 관계가 되는 것이다.

 

 

연관관계 정의 규칙 中 2번째 - 연관관계의 주인
두 객체(A , B)가 양방향 관계 (즉, 단방향 관계 2개 :  A → B, B ← A)를 맺을 때 연관관계의 주인role을 지정해야 함

 

-의미 : 연관관계의 주인ROLE을 지정하는 것 ▶ 두 단방향 관계 中 제어의 권한(외래키,테이블 레코드 저장,수정,삭제 처리)를 갖는 실질적인 관계가 어떤 것이고, 누가 그 실질적인 주인 ROLE을 맡게 되었는지 JPA에게 알려주는 것

연관관계의 주인 ROLE : 연관관계를 갖는 두 객체 사이에서 조회,저장,수정,삭제 다 가능 

 

하지만 HOWEVER!!!!!!!!!

연관관계의 노예(?) ROLE : 오로지 조회만 가능

 

연관관계의 주인 ROLE 정하는 TIP !!!! : 외래키(FK)가 있는 곳을 연관관계의 주인으로 지정하면 된다 무조건 백퍼센트

 

 

- 왜? WHY? 연관관계의 주인을 정해야 하는 거죠?

요약 : 연관관계의 주인을 정해야 하는 이유 - 두 객체 사이의 관계에 있어서 '기준'이 되는 연관관계의 주인을 명확하게 정해야 JPA가 혼란이 오지 않기 때문

EX. Board(게시판), Post(게시글) 두 객체가 있고 Board → Post, Post → Board (두 개의 단방향 연관 관계) 양방향 연관 관계를 가지고 있음.

if 에피소드 1) 게시글(Post)의 게시판을 다른 게시판(Board)로 수정하려고 할 때 문제 발생함 -> 어떻게 해결하지?
방법1. Post 객체에서 setBoard(...)같은 메서드를 이용해서 수정하는 게 맞는지 
방법2. Board 객체에서 getPosts()같은 메서드를 이용해서 List의 게시글을 수정하는 게 맞을지...
끊이지 않는 고민에 휩싸인 개발자...

특히, '양방향 연관 관계의 두 객체'가 연관 관계 관리의 포인트일 때, 테이블&매핑을 담당하는 JPA는 더 혼란이 옴
↳ Post에서 Board를 수정할 때, FK를 수정할 지 / Board에서 Post를 수정할 때, FK를 수정할 지 깊은 딜레마에 빠짐

 

개발하다보면 이런 상황이 많이 발생하기 때문에, 

'기준'이 되는 두 객체 사이의 연관 관계의 주인을 명확하게 정해야 하는 것

   ↳즉, Post에서 Board를 수정하려 할 때만 FK를 수정하겠다!! 라고 정하는 것 

 

Q. DB에 외래키(FK)가 있는 테이블을 수정하려면, 연관관계의 주인만 변경하는 게 맞나요?

A. 넵!!!! BUT, 객체들을 생각한다면 연관관계의 주인 ROLE, 노예 ROLE 둘 다 변경해주는 것이 좋다 (안심)

 

 

 

연관관계 정의 규칙 中 3번째 - 다중성
다중성 : 데이터베이스 기준으로 다중성을 결정함 (비교 : 보통 JPA는 객체가 기준인데 반해서)
다대일 / 일대다 / 일대일 

 

1) 다대일 - 기준 : '다' 쪽 (공식 : 주로 '다' 쪽이 연관 관계의 주인 ROLE을 가짐 & 외래키는 보통 '다'쪽에 달아놓음)

EX. 게시판(Board) 와 게시글(Post)를 가지고 개념을 설명할게요!!

요구사항
1. 1개의 게시판에는 N(多) 개의 게시글을 쓸 수 있다.
2. 1개의 게시글은 1개의 게시판에만 쓸 수 있다.
3. 그래서, 게시글과 게시판은 多 : 1의 관계를 가진다.

결론 : 이런 경우에는, DB를 기준으로 다중성 (게시글 多 : 게시판 1)을 결정 & 외래키(FK)는 보통 多쪽에 달아놓으므로 Post(多)에 FK키를 달기

 

ⅰ) 다대일 단방향으로 설정하려면 

  • 쪽에서 1쪽 객체에 @ManytoOne 어노테이션 달아주기
  • 반대쪽인 1쪽 객체는 아무것도 하지 않기

ⅱ) 다대일 양방향으로 만들려면

  • 쪽에서 1쪽의 객체에 @ManytoOne 어노테이션 달아주기
  • 반대편 1쪽 객체에서는 쪽의 객체에 @OnetoMany 어노테이션 달아주기 & mapped by = "연관관계 1쪽(노예)" 적기

TIP) mapped by : 연관관계에 있어서 주인 ROLE이 아님을 설정하는 명령어 + 노예  ROLE 낙인

TIP) mapped by 뒤에는 '연관관계 多 쪽(주인)' 을 적지 않는다

 

 

 

2) 일대다 - 기준 : '1' 쪽(노예 ROLE) 입장에서 필기를 정리한 것

 

ⅰ) 일대다 단방향으로 설정하려면 ※ 실무에서는 잘 안씀

  • 1쪽에서 쪽의 객체에 @OneToMany 어노테이션 달아주기
  • 양방향이 아니기 때문에 mapped by 조건은 달지 않아도 됨
  • 대신에, 1쪽에서 쪽의 객체에 @JoinColumn 어노테이션을 필수로 기재해서 join하도록 한다.

   ↳ 일대다 단방향 연관 관계 매핑의 단점 : 1쪽에서 多 쪽의 FK키를 저장할 방법이 없다는 것이다. 그래서 실무에서는 거의 쓰지 않는다.

그래서 SO!!!!

앞서 설명한 다대일 양방향 연관 관계를 매핑하여 사용하는 것이 나중에 유지보수 측면에서도 더 낫다...

 

ⅱ) 일대다 양방향 : 실무에서 안씀

 

일대다 (단방향, 양방향) 요약 : 일대다 단방향이든 양방향이든 쓸 바에... 차라리 다대일 양방향으로 쓰는 게 낫다.

 

 

3) 일대일 : 주 테이블(주인 ROLE)에 외래키(FK키)를 심을수도, 반대로 대상 테이블(노예 ROLE)에 외래키(FK키)를 심을 수도 있다.

 

ⅰ) 일대다 단방향으로 설정하려면 ( = 외래키 (FK키)를 주 테이블에서 가지고 있다는 가정하에)

 EX. Post테이블(주 테이블)의 FK키 - Attach 테이블(대상 테이블)의 PK키 -> 게시글(Post)에 첨부파일(Attach)을 반드시 1개만 첨부할 수 있다고 가정함

 

단순하다. 쉽다. 뭐 더 할 거 딱히 없다.

 

 

ⅱ) 일대일 양방향으로 설정

 

  • 단순하게 @OnetoOne 어노테이션 설정 & mapped by + 노예(대상 테이블) 설정해서, 읽기 전용으로 만들기

 

요약 : 일대일 (단방향, 양방향) 경우, 주 테이블(주인 ROLE, POST)에 FK키(외래키) 두기