티스토리 뷰
Overview
객체와 테이블과 연관관계의 차이를 이해하기합니다.
예제 시나리오
단방향 연관관계에 대해 설명하기 위해 아래와 같이 세 가지 상황을 가정합니다.
- 회원과 팀
- 회원은 하나의 팀에만 소속될 수 있음
- 회원:팀=N:1
연관관계가 필요한 이유
예제 시나리오의 상황을 다이어그램으로 나타내면 다음과 같습니다.
- 객체 연관관계
- 테이블 연관관계
테이블에 맞춰서 객체를 모델링하게되면 서로 아무 관계가 없는 객체가 되어버립니다.
테이블끼리는 FK
를 이용해 관계를 나타낼 수 있지만 객체는 다른 객체의 ID
를 갖고있다고해도 서로 관계가 있다고 보긴 힘듭니다.
이를 자바 코드로 나타내면 다음과 같습니다.
package com.tistory.jaimenote.jpa.domain.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
private Long teamId;
}
package com.tistory.jaimenote.jpa.domain.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
}
Member
객체만 있을 때 Team
객체를 참조할 수 없고 역으로도 마찬가지입니다.
애플리케이션을 실행시켜서 테이블이 생성된 것을 확인해보겠습니다.
2022-06-25 01:40:51.223 DEBUG 4182 --- [ main] org.hibernate.SQL :
create table member (
id bigint not null,
name varchar(255),
team_id bigint,
primary key (id)
)
2022-06-25 01:40:51.227 DEBUG 4182 --- [ main] org.hibernate.SQL :
create table team (
id bigint not null,
name varchar(255),
primary key (id)
)
두 개의 테이블이 생성되었는데 FK
로 설정되어있지 않고, 객체를 다룰 때도 FK
에 해당하는 Team ID
를 직접 다뤄야하는 불편함이 있습니다.
간단한 테스트로 확인해보면,
package com.tistory.jaimenote.jpa;
import com.tistory.jaimenote.jpa.domain.entity.Member;
import com.tistory.jaimenote.jpa.domain.entity.Team;
import com.tistory.jaimenote.jpa.infra.repository.MemberRepository;
import com.tistory.jaimenote.jpa.infra.repository.TeamRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.Rollback;
@DataJpaTest
public class WithoutRelationTest {
@Autowired
MemberRepository memberRepository;
@Autowired
TeamRepository teamRepository;
@Test
@Rollback(false) // 로그 출력을 위해 설정
void saveTest() {
Team team = Team.withName("토트넘");
teamRepository.save(team);
Member member = Member.withName("손흥민").withTeamId(team.getId());
memberRepository.save(member);
}
}
Hibernate:
insert
into
team
(name, id)
values
(?, ?)
2022-06-25 02:05:14.566 TRACE 6080 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [토트넘]
2022-06-25 02:05:14.569 TRACE 6080 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
Hibernate:
insert
into
member
(name, team_id, id)
values
(?, ?, ?)
2022-06-25 02:05:14.576 TRACE 6080 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [손흥민]
2022-06-25 02:05:14.576 TRACE 6080 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
2022-06-25 02:05:14.577 TRACE 6080 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [2]
정상적으로 DB
에 insert
되었고, 쿼리를 이용해서는 FK
를 사용해 JOIN
할 수 있게 되었습니다.
하지만 직접 쿼리를 작성하지 않고 Repository
를 통해 조회하려면 아래와 같은 방법으로밖에 조회할 수 없습니다.
Member member = memberRepository.findById(2L)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 ID"));
Team team = teamRepository.findById(member.getTeamId())
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 ID"));
매번 이런식으로 해야한다면 너무 불편하겠죠?
따라서 객체를 테이블에 맞춰 데이터 중심으로 모델링하게 되면 관계를 제대로 형성할 수 없습니다.
테이블이 FK
를 이용해 JOIN
으로 연관된 테이블을 찾을 수 있다면 객체는 객체간 참조를 사용해서 연관된 객체에 접근할 수 있습니다.
이러한 연관관계가 JPA를 이용하여 어떻게 표현될 수 있는지 다음 포스팅부터 다뤄보도록 하겠습니다.
'JPA' 카테고리의 다른 글
[JPA] 단방향 연관관계 (0) | 2022.06.28 |
---|---|
스프링 부트 JPA 예약어 컬럼명 사용하기 (0) | 2022.06.27 |
스프링 데이터 JPA - 새로운 Entity 판별 (3) | 2021.07.14 |
스프링 데이터 JPA - JPA 구현체 분석 (0) | 2021.07.13 |
스프링 데이터 JPA - 페이징과 정렬2(API 활용) (0) | 2021.07.12 |
- Total
- Today
- Yesterday
- spring boot app
- 헥사고날 아키텍처
- Jackson
- @ManyToOne
- 스프링 부트 애플리케이션
- r
- QueryDSL
- gRPC
- Spring Data JPA
- JPA
- 알고리즘
- Spring Boot Tutorial
- 함께 자라기
- 스프링 부트 튜토리얼
- proto3
- intellij
- Spring Boot JPA
- Spring Boot
- 스프링 부트
- 스프링 부트 회원 가입
- 클린 아키텍처
- spring boot application
- 스프링부트
- Java
- spring boot jwt
- 함께 자라기 후기
- 스프링 데이터 jpa
- Linux
- JSON
- leetcode
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |