일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- SpringBootTest
- 빈 스코프
- Controller
- Java Reflection API
- 기본 생성자
- ResponseEntity
- 가을야구
- 키움
- RunWith
- 정적 컨텐츠
- jdbc template
- 컴포넌트 스캔
- JPA
- 스프링 IoC 컨테이너
- 테스트 코드
- 통합 테스트
- testresttemplate
- 405 METHOD_NOT_ALLOWED
- restTemplate
- 스프링 데이터 JPA
- 의존성 주입
- Not Acceptable
- 의존관계 자동 주입
- 스프링 컨테이너
- 랜덤 포트
- 406 NOT_ACCEPTABLE
- 스프링
- jdbc
- 좋은 객체지향 설계 원칙
- entity
- Today
- Total
코드네임 JY
[스프링 JPA] 연관관계 매핑 (2) 본문
🍳 다중성
다대일 (N : 1)
'다대일' 관계는 '다' 방향에서 항상 연관관계의 주인 을 가진다! 생각을 조금만 해보면 알 수 있다.
'일' 방향에서 여러 데이터를 가지고 있어야하는데, DB 테이블에는 한 컬럼에 리스트 형태로 데이터를 담을 수 없다.
따라서 '다' 방향에서 어떤 PK 값과 연결되어야 하는지 알려주는 FK 값을 가져야 하고, 여기서는 연관관계의 주인이다!
그리고 '일' 방향에서 반대편의 데이터를 조회할 수 있다! 내가 여기서 잠깐 간과했던 것이..
위에서 말했던 것! "DB 테이블에는 한 컬럼에 리스트 형태로 데이터를 담을 수 없다" 라는 사실이다.
엔티티를 볼 때는 musics 라는 리스트 가 추가되었지만 실제 데이터베이스와는 전혀 상관없는 필드 이다.
이는 단순히 조회용 리스트 일 뿐이다! 데이터베이스 테이블 구조와 엔티티 구조를 헷갈리지 않도록 하자!
✅ 다대일 관계에서는 '다' 방향이 FK 값을 가진다! '일' 방향에서는 리스트로 단순 조회만 가능하다!
✅ 데이터베이스 테이블 구조를 먼저 작성하고, 그 다음에 엔티티 구조를 작성하도록 하자! 그래야 코드 작성할 때 안 헷갈린다!
일대다 (1 : N)
자바에서 플레이리스트(이하 '플리')는 음악 리스트를 담을 수 있게 구현했다고 하자.
하지만 실제 데이터베이스 테이블을 보면 FK 값은 MUSIC 테이블에 위치 해 있다. 그럴 수 밖에 없기도 하고! (위에서 말했음)
기능 구현 단계에서, 플리에서 음악을 삭제해야하는 로직을 짜고 싶다고 가정하자. 자바에서는 쉽게 구현할 수 있다.
하지만 데이터베이스 테이블 입장에서 볼 때는? 엔티티가 관리하는 FK 값이 반대 테이블에 있는 상황 이다..
그러면 PLAYLIST만 UPDATE 쿼리를 날리고 싶은데, FK가 반대 테이블에 있는 관계로 MUSIC에도 쿼리를 날려야한다..
이런 단점이 있다..! 별로 좋지 않은 관계고 최대한 다대일 방식으로 풀어내는 것이 좋다!
✅ 단점이 있다면? '일' 방향이 연관관계의 주인이 되므로, FK가 반대 테이블에 위치하게 된다.
✅ 쿼리를 다른 테이블에도 날려줘야한다는 단점이 생긴다!
일대일 (1 : 1)
일대일 관계는 쉽다! 다대일 관계랑 비슷한데 바뀐 것이 있다면, 한쪽 방향이 '다' 가 아닌 '일' 이라는 점이다!
이는 연관관계의 주인이 어느 쪽이던 상관없다! 즉, FK를 어느 쪽에서 가지던 상관이 없는데..! 약간의 차이는 있다.
MUSIC 테이블을 주 테이블이라고 하고, RATING 테이블을 대상 테이블이라고 하자.
사실 프로젝트의 정서(?) ㅋㅋㅋ 주제 상!! RATING 테이블 보다는 MUSIC 테이블이 더 핵심이라고 생각해서 그런다.
주 테이블만 조회해도 대상 테이블의 데이터를 확인 할 수 있지만, 만약 값이 없다면 null 값이 들어가야 하는 것 이 단점이다.
대상 테이블은 '다' 관계를 갖게 되었을 때 FK가 있으므로 구조 변경이 없어도 되지만, 항상 지연 로딩된다 는게 단점이다.
✅ 누가 연관관계의 주인을 하던 큰 상관이 없다!
✅ 개발자 입장에서는 왠만하면 주 테이블이 연관관계의 주인이 되는 것이 좋을 수도..
다대다 (N : M)
사실 일대다 부분에서 설명한 예제는 약간 틀렸다..! 하나의 음악도 여러 플리에 공유될 수 있지 않나!!
그래서 PLAYLIST와 MUSIC은 서로 다대다 관계이다! 다대다 관계는 어떻게 구현할 수 있을까?
두 테이블 사이에 연결 테이블 을 하나 만들고, 자바에서는 이를 엔티티로 승격 시켜서 다대다 관계를 구현할 수 있다.
하지만 이는 절대로 실무에서 사용하면 안 된다 고 한다! 여러 데이터들이 중간에 포함될 경우 복잡해질 수도 있다.
일단 나도 개인 프로젝트이기 때문에 다대다 방식으로 이를 구현했지만, 더 좋은 방법은 없을지.. 생각해봐야 한다!!
✅ 다대다 방식은 실무에서 사용하면 안 된다고 한다..!
✅ 구현해야하는 상황이라면, 일대다 + 다대일 관계로 풀어내서 구현해야 한다!
🫕 상속관계 매핑
자바에는 '상속' 개념이 존재한다. 하지만 관계형 데이터베이스에서는 '상속' 개념이 존재하지 않는다.
대신 '슈퍼타입' 과 '서브타입' 이라는 개념이 존재한다. 슈퍼타입은 '공통 속성' 서브타입은 '고유 속성' 이라고 보면 된다.
슈퍼타입과 서브타입을 사용해서 관계형 데이터베이스에서도 상속 과정을 유사하게 구현할 수 있다.
위 사진의 왼쪽 구조도를 '논리 모델' 이라고 하고, 아래처럼 실제 구현하는 것을 '물리 모델' 이라고 한다.
다음 3개의 물리 모델이 있다.
1. 조인 전략 (Identity)
✅ 슈퍼 타입은 공통이고, 각각의 서브타입만 분리
✅ 유용한 경우 : 예시로 나머지는 조회 아직 필요 없고, Book의 Author 정보만 먼저 필요한 경우!
✅ @Inheritance(strategy = InheritanceType.JOINED) 어노테이션 사용
✅ 장점 : 테이블이 정규화(중복이 최소화되도록 데이터를 구조화) 되어 있음
✅ 단점 : JOIN 쿼리가 많이 필요해서 쿼리 자체가 조금 복잡함
2. 단일 테이블 전략 (Rollup)
✅ 하나의 테이블로 통합
✅ 유용한 경우 : 예시로 Album, Movie, Book이 모두 통합되어 함께 처리되어야 하는 경우!
✅ @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 어노테이션 사용
✅ 장점 : JOIN 쿼리가 필요 없어서 쿼리가 단순하고 조회 성능이 빠름
✅ 단점 : 관련 없는 필드일 경우 null 값이 들어가고, 테이블의 크기가 급성장함 (커져라~!! 크게! 크게!!)
3. 구현 클래스마다 테이블 전략 (Rolldown)
✅ 슈퍼 타입을 각각의 서브타입 테이블에 분리
✅ 유용한 경우 : Movie, Book 객체가 Album 객체에 비해서 엄청나게 많은데 Album만 조회하고 싶은 경우!
✅ @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 어노테이션 사용
✅ 장점 : 서브 타입의 구분이 명확해짐
✅ 단점 : 조회도 느리고 자식 테이블을 통합하기도 어려움 그냥 이건 비추한다고 한다!
이제는 전체적인 클래스에 대해서 공통 매핑 정보가 필요하다면? 그때 사용할 수 있는 어노테이션이 하나 있다.
바로 @MappedSuperclass 라는 어노테이션이다. 이는 테이블과 전혀 관계 없다!
엔티티들이 공통적으로 사용하는 데이터를 매핑하는 역할이고, 직접 테이블로 사용할 일이 없어서 추상 클래스로 구현한다.
가끔 책이나 다른 사람의 프로젝트를 보면 BaseTimeEntity 클래스가 있는데 이 방식으로 구현한 것이다!
예를 들어 게시판 작성 프로젝트일 경우, 작성 시간.. 작성한 사람.. 등의 정보를 이 클래스에 적을 수 있는 것이다!
'백엔드 공부' 카테고리의 다른 글
[프로젝트] 테이블 설계 & 엔티티 세팅 (0) | 2023.02.14 |
---|---|
[프로젝트] 요구사항 분석 및 구현 단계 (0) | 2023.02.14 |
[스프링 JPA] 연관관계 매핑 (1) (0) | 2023.02.10 |
[스프링 JPA] 엔티티 매핑 (0) | 2023.02.09 |
[스프링 JPA] 영속성 컨텍스트 (0) | 2023.02.08 |