📘 목차
1. 연관관계 매핑
연관관계의 종류
- 관계 타입
- N:1 (ManyToOne)
- 1:N (OneToMany)
- 1:1 (OneToOne)
- N:M (ManyToMany)
- 방향성
- 단방향: 한쪽 엔티티만 상대 엔티티를 참조
- 양방향: 양쪽 엔티티가 서로를 참조
주요 어노테이션
관계 타입 | 어노테이션 | 비고 |
N : 1 | @ManyToOne | 가장 많이 사용됨 |
1 : N | @OneToMany | |
1 : 1 | @OneToOne | |
N : M | @ManyToMany | 신중하게 사용 권장 |
단방향과 양방향 연관관계
- 테이블 관점
- 외래 키(FK) 하나로 두 테이블 간 JOIN 가능
- 객체 관점
- 단방향: 외래키가 있는 쪽 엔티티만 상대 엔티티를 참조 가능
- 양방향: 두 엔티티 모두 서로를 참조, 단방향 연관관계 두 개가 모여 양방향 관계가 됨
연관관계의 주인 (Owner)
- 연관관계 주인: 외래키(FK)를 직접 관리하는 객체(엔티티)
- 주인이 아닌 쪽: 단순 조회용으로만 사용 가능, 연관관계 변경 시 주인만 DB에 반영됨
요약
관계 타입 | 방향성 | 외래키 위치 | 연관관계 주인 | 특징 |
1 : N | 단방향 | N 쪽 테이블 | 1 쪽 | N 쪽은 1 쪽 참조 못함 |
1 : N | 양방향 | N 쪽 테이블 | N 쪽 | 양쪽 탐색 가능, N 쪽이 주인 |
1 : 1 | 단방향 | 참조하는 쪽 테이블 | 참조하는 쪽 | 외래키가 있는 쪽이 주인 |
1 : 1 | 양방향 | 외래키가 있는 쪽 | 외래키 쪽 | 양쪽 탐색 가능 |
N : M | 단/양방향 | 중간 테이블 | 중간 테이블 | 중간 테이블에 속성 추가 어려움 |
2. 1 : N 연관관계
1 : N 단방향
- 한 쪽(1)에만 연관관계가 설정되어 있음.
- 예: Order → 여러 OrderItem (Order가 OrderItem을 참조하지만, OrderItem은 Order를 모름)
- 구현: 보통 1(N) 쪽에 외래키가 있어서, 1 쪽에서 컬렉션으로 관리.
- 문제점: 단방향이므로 N 쪽에서 1 쪽 참조가 불가능.
@Entity
public class Order {
@Id
private Long id;
@OneToMany
@JoinColumn(name = "order_id") // 외래키를 OrderItem 테이블에 생성
private List<OrderItem> orderItems;
}
1 : N 양방향
- 1 쪽과 N 쪽 모두가 서로를 참조.
- 예: Order ↔ OrderItem
- 구현: N 쪽에 외래키가 존재하며, N 쪽이 연관관계의 주인(owning side)임.
- 1 쪽은 mappedBy 속성으로 연관관계의 주인이 아님을 명시.
- 장점: 양쪽에서 객체 탐색 가능.
- 주의점: 연관관계 관리 시 N 쪽 주인 쪽 객체를 변경해야 연관관계가 제대로 반영됨.
@Entity
public class Order {
@Id
private Long id;
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems;
}
@Entity
public class OrderItem {
@Id
private Long id;
@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
}
3. 1 : 1 연관관계
1 : 1 단방향
- 한 쪽에서만 상대 객체를 참조.
- 예: Member → Locker (Member가 Locker를 참조하지만 Locker는 Member를 모름)
- 외래키를 어느 쪽에 둘지 결정해야 함.
@Entity
public class Member {
@Id
private Long id;
@OneToOne
@JoinColumn(name = "locker_id")
private Locker locker;
}
1 : 1 양방향
- 양쪽에서 서로 참조.
- 외래키를 어느 쪽에 둘지 결정하며, 외래키가 있는 쪽이 연관관계의 주인임.
- 주인은 외래키가 존재하는 쪽으로 지정.
@Entity
public class Member {
@Id
private Long id;
@OneToOne(mappedBy = "member")
private Locker locker;
}
@Entity
public class Locker {
@Id
private Long id;
@OneToOne
@JoinColumn(name = "member_id")
private Member member;
}
1 : 1 연관관계 외래 키
- 외래키는 보통 한 쪽 테이블에 단일 컬럼으로 존재.
- 외래키는 반드시 유니크 제약조건이 있어야 1:1 관계를 보장.
4. N : M 연관관계
N : M 기본 매핑
- 두 엔티티가 서로 다대다 관계.
- 예: Student ↔ Course (학생은 여러 강의를 듣고, 강의는 여러 학생이 수강)
@Entity
public class Student {
@Id
private Long id;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses;
}
@Entity
public class Course {
@Id
private Long id;
@ManyToMany(mappedBy = "courses")
private List<Student> students;
}
N : M 단방향, 양방향
- 단방향: 한 쪽에서만 상대 객체를 참조.
- 양방향: 서로 참조 가능.
N : M 매핑의 문제점
- 중간 테이블에 추가 속성을 넣기 어렵다.
- 실무에서는 중간 테이블을 엔티티로 분리해서 1:N, N:1 관계로 풀어 관리한다.
5. 상속관계 매핑
테이블 전략 종류
- 단일 테이블 전략 (Single Table)
- 모든 클래스 정보를 하나의 테이블에 저장.
- 구분 컬럼(discriminator column)으로 어떤 클래스 인지 구분.
- 장점: 조회 시 조인 불필요, 성능 우수.
- 단점: NULL 컬럼 많아짐, 테이블 크기 커짐.
- 조인 전략 (Joined)
- 슈퍼클래스 테이블과 서브클래스 테이블을 분리.
- 서브클래스는 슈퍼클래스 PK를 외래키로 참조.
- 조회 시 조인 필요.
- 장점: 정규화된 테이블 구조.
- 단점: 조회 시 조인으로 인한 성능 저하 가능.
- 테이블 per 클래스 전략 (Table per Class)
- 각 클래스마다 별도의 테이블 생성.
- 슈퍼클래스 필드 포함.
- 조회 시 UNION 쿼리 사용.
- 장점: 테이블 구조 단순.
- 단점: UNION으로 조회 성능 저하 가능.
JPA의 테이블 전략 설정
- @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
- @Inheritance(strategy = InheritanceType.JOINED)
- @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
- 구분 컬럼은 @DiscriminatorColumn으로 지정 가능하며, 기본값은 DTYPE.
'Spring > 강의' 카테고리의 다른 글
[📘 심화 Spring] 3-1. Spring Bean 생명주기 (0) | 2025.06.09 |
---|---|
[📘 심화 Spring] 2-2. JPA 고급 매핑 (0) | 2025.06.09 |
[📘 심화 Spring] 1. Converter, Formatter (0) | 2025.06.09 |
[📙 숙련 Spring] 3-5. Spring Data JPA 실습 (0) | 2025.05.21 |
[📙 숙련 Spring] 3-4. Entity 설계 실습 (2) | 2025.05.21 |