티스토리 뷰
1. 연관관계 매핑
엔티티들은 대부분 다른 엔티티와 연관관계들이 있습니다.
예를 들어, 회원과 팀이 있다고 가정하면 회원은 특정 팀에 속할 수 있고, 팀은 여러 회원을 가질 수 있습니다.
이 둘의 관계를 객체와 테이블로 어떻게 나타내는지 살펴봅시다.
Member 객체가 Team 객체를 참조하기 위해서는 teamId가 아닌 Team 객체를 참조(주소)로 관계를 맺습니다.
반면, 테이블은 teamId를 이용해서 외래 키를 사용해 관계를 맺습니다.
👉🏻 객체의 참조와 테이블의 외래 키를 매핑하는 것을 JPA를 이용해 어떻게 표현하는지 알아보도록 하겠습니다.
우선 위 사진에서 객체 모델링한 것을 코드로 표현해 보도록 하겠습니다.
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Member {
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
// 1. 연관관계 매핑
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
// 2
private Member(String username) {
this.username = username;
}
// 3
public static Member createMember(String username) {
return new Member(String username);
}
// 4. 연관관계 설정
public void setTeam(Team team) {
this.team = team;
}
}
1. @ManyToOne 을 통해 다대일 관계임을, @JoinColumn을 통해 테이블의 외래 키(TEAM_ID)를 매핑합니다.
2. 외부에서 Member 객체를 이름 없이는 생성할 수 없도록 private 생성자를 사용합니다.
3. 외부에서 객체를 생성할 때 이름을 있어 Member를 생성할 수 있도록 합니다.
4. 외부에서 팀을 세팅하기 위한 설정입니다.
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
private Team(String name) {
this.name = name;
}
public static Team createTeam(String name) {
return new Team(name);
}
}
MySQL 데이터베이스로 설정했을 경우 아래와 같은 로그를 확인할 수 있습니다.
// 회원 테이블 로그
create table Member (
MEMBER_ID bigint not null auto_increment,
username varchar(255),
TEAM_ID bigint,
primary key (MEMBER_ID),
foreign key (TEAM_ID) references Team (id) -- TEAM_ID는 Team 테이블의 id 열을 참조
);
// 팀 테이블 로그
create table Team (
id bigint not null auto_increment,
name varchar(255),
primary key (id)
);
어노테이션을 매핑을 통해 실제 데이터베이스에는 외래 키 제약 조건이 생성되어 매핑된 것을 볼 수 있습니다.
👉🏻 이렇게 객체 간의 참조를 어노테이션(@ManyToOne, @JoinColumn)을 활용하여 매핑을 할 수 있습니다.
2. 연관관계 사용
연관관계 설정을 통해 객체지향적으로 사용가능한지 살펴보도록 하겠습니다.
public class Test {
// 팀을 생성하는 코드
Team team = Team.createTeam("Team");
// 회원을 생성하고 팀을 설정하는 코드
Member member1 = Member.createMember("member1");
Member member2 = Member.createMember("member2");
// 회원들에게 팀을 설정
member1.setTeam(team);
member2.setTeam(team);
// 출력하여 관계를 확인하는 코드
System.out.println(member1.getUsername() + " is in team: " + member1.getTeam().getName());
System.out.println(member2.getUsername() + " is in team: " + member2.getTeam().getName());
}
출력되는 두 코드를 확인하면 Team을 찾기 위해서 Member를 이용해 Team를 찾았습니다.
객체는 Member에서 Team으로 단방향 참조만 일어나기 때문에 Team을 이용해 Member 찾는 것은 불가능합니다.
반면, 데이터베이스에서는 TEAM을 먼저 찾고, TEAM_ID를 이용해 TEAM의 전체 MEMBER를 찾아낼 수 있습니다.
👀 객체 연관관계 VS 테이블 연관관계
테이블에서는 외래 키로 테이블들과의 연관관계를 맺기 때문에 항상 양방향 관계이다.
하지만 객체는 위에 예시처럼 단방향인 경우도 있습니다. 만약 양방향으로 만들고 싶다면 반대 객체에도 필드를 추가해 연관관계를 추가해 주시면 됩니다! 하나 주의할 점은 이는 양방향 관계가 아니라 서로 다른 단방향 관계가 2개임을 알고 추가해주셔야 합니다.
👉🏻 이렇게 객체에서 한 방향으로만 참조할 수 있는 관계를 단방향 연관관계라고 합니다.
본 포스팅은 자바 ORM 표준 JPA 프로그래밍을 참고하여 작성했습니다.
'JPA' 카테고리의 다른 글
연관관계의 주인 (0) | 2024.04.25 |
---|---|
양방향 연관관계(@OneToMany, mappedBy) (0) | 2024.04.25 |
기본 키 매핑(@Id, @GeneratedValue) (1) | 2024.04.23 |
JPA 데이터베이스 스키마 자동 생성 (0) | 2024.04.22 |
JPA 매핑 어노테이션(@Entity, @Table) (0) | 2024.04.21 |
- 비동기
- 스키마 자동 생성
- JPA
- 최적화
- 메일
- @GeneratedValue
- @OneToMany
- N + 1
- @Table
- @joincolumn
- 엔티티 매니저
- Redis
- @TransactionalEventListener
- @ManyToOne
- onetoone
- 조인 전략
- @Entity
- 1차 캐시
- 비영속
- 인메모리 db
- @Cacheable
- mappedBy
- @MappedSuperclass
- 단일 테이블 전략
- 준영속
- 연관관계
- 즉시 로딩
- 변경감지
- @Id
- 영속성 컨텍스트