JPA에서 연관관계를 정의할 때 주로 사용되는 관계는 일대일(1:1), 일대다(1:N), 다대일(N:1), 다대다(N:M) 네 가지입니다. 각각의 관계는 엔티티 간의 데이터 참조 방식에 따라 결정되며, 이를 정의하기 위해 JPA에서는 어노테이션을 사용합니다.
아래에서 각 연관관계의 특징과 구현 방법을 설명하고, 예제를 제공합니다.
1. 일대일 (One-to-One)
특징
• 한 엔티티는 다른 엔티티와 1:1로 매핑됩니다.
• 두 엔티티 중 하나가 외래 키를 소유하거나, 별도의 테이블을 통해 관계를 설정할 수 있습니다.
예제: 사용자와 프로필
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Profile profile;
}
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bio;
@OneToOne
@JoinColumn(name = "user_id") // 외래 키
private User user;
}
주요 어노테이션
• @OneToOne: 일대일 관계를 나타냄.
• @JoinColumn: 외래 키를 정의. (여기선 Profile이 외래 키를 소유)
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "profile_id") // 외래 키
private Profile profile;
속성 | 설명 | 기본값 |
cascade | 부모 엔티티의 작업(Persist, Remove 등)을 자식 엔티티에 전파.(CascadeType 열거형 사용) | 없음 |
fetch | 데이터를 가져오는 방식 (FetchType.LAZY or FetchType.EAGER) | FetchType.EAGER |
mappedBy | 양방향 관계에서 외래 키를 관리하는 빌드 지정(연관 관계의 주인을 정의). | 없음 |
optional | 관계 대상 엔티티가 null이어도 되는지 여부 설정 | true |
orphanRemoval | 부모 엔티티와의 관계가 끊어진 자식 엔티티를 자동 삭제 | false |
2. 다대일 (Many-to-One)
특징
• 여러 엔티티가 하나의 엔티티를 참조합니다.
• 주로 관계의 주인은 “다”쪽에 설정됩니다.( 관계의 주인은 외래 키를 소유하고 관리하는 엔티티)
예제: 주문과 사용자
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
@ManyToOne
@JoinColumn(name = "user_id") // 외래 키
private User user;
}
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Order> orders = new ArrayList<>();
}
주요 어노테이션
• @ManyToOne: 다대일 관계를 나타냄.
• @JoinColumn: 외래 키를 정의.
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name = "user_id", nullable = false) // 외래 키
private User user;
속성 | 설명 | 기본값 |
cascade | 부모 엔티티 작업을 자식 엔티티에 전파. | 없음 |
fetch | 데이터를 가져오는 방식(FetchType.LAZY or FetchType.EAGER) | FetchType.EAGER |
optional | 관계 대상 엔티티가 null이어도 되는지 여부 설정. | true |
3. 일대다 (One-to-Many)
특징
• 한 엔티티가 여러 엔티티를 참조합니다.
• @OneToMany는 기본적으로 관계의 주인이 아니므로, 외래 키는 @ManyToOne 쪽에 설정됩니다.
예제: 사용자와 주문
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Order> orders = new ArrayList<>();
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
@ManyToOne
@JoinColumn(name = "user_id") // 외래 키
private User user;
}
주요 어노테이션
• @OneToMany: 일대다 관계를 나타냄.
• mappedBy: 관계의 주인을 설정. (user 필드와 매핑)
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Order> orders = new ArrayList<>();
속성 | 설명 | 기본값 |
cascade | 부모 엔티티 작업을 자식 엔티티에 전파. | 없음 |
fetch | 데이터를 가져오는 방식(FetchType.LAZY or FetchType.EAGER). | FetchType.LAZY |
mappedBy | 양방향 관계에서 외래 키를 관리하는 필드 지정(연관 관계의 주인을 정의). | 없음 |
orphanRemoval | 부모 인티티와의 관계가 끊어진 자식 엔티티를 자동 삭제 | false |
4. 다대다 (Many-to-Many)
특징
• 여러 엔티티가 여러 엔티티와 참조 관계를 가집니다.
• 다대다 관계는 중간 테이블을 사용하여 매핑합니다.
예제: 학생과 수업
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
@JoinTable(
name = "student_course", // 중간 테이블
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses = new ArrayList<>();
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@ManyToMany(mappedBy = "courses")
private List<Student> students = new ArrayList<>();
}
주요 어노테이션
• @ManyToMany: 다대다 관계를 나타냄.
• @JoinTable: 중간 테이블 정의.
• joinColumns: 현재 엔티티의 외래 키 설정.
• inverseJoinColumns: 상대 엔티티의 외래 키 설정.
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses = new ArrayList<>();
속성 | 설명 | 기본값 |
casacade | 부모 엔티티 작업을 자식 엔티티에 전파 | 없음 |
fetch | 데이터를 가져오는 방식(FetchType.LAZY or FetchType.EAGER). | FetchType.LAZY |
mappedBy | 양방향 관계에서 외래 키를 관리하는 필드 지정. | 없음 |
5. 양방향과 단방향
• 단방향: 한쪽에서만 연관 관계를 정의.
• 간단하고 직관적이며, 관계가 간단할 때 적합.
• 양방향: 양쪽 엔티티에서 서로를 참조.
• mappedBy를 통해 관계의 주인을 설정해야 함.
• 관계를 명확히 하고 데이터를 쉽게 탐색 가능.
단방향 예제
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
양방향 예제
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Order> orders = new ArrayList<>();
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
6. Cascade와 Fetch 옵션
(1) Cascade
• 연관 엔티티를 함께 저장, 삭제할 때 사용.
• 주요 옵션:
• CascadeType.PERSIST: 부모 저장 시 자식도 저장.
• CascadeType.REMOVE: 부모 삭제 시 자식도 삭제.
• CascadeType.ALL: 모든 Cascade 옵션 적용.
(2) Fetch
• 연관 데이터를 언제 가져올지 설정.
• 주요 옵션:
• FetchType.LAZY: 연관 데이터를 실제로 사용할 때 조회(기본값).
• FetchType.EAGER: 엔티티를 조회할 때 즉시 연관 데이터도 함께 조회.
7. 정리
• 연관 관계는 비즈니스 요구사항에 따라 선택.
• 단방향과 양방향 관계를 적절히 설계.
• 성능 최적화를 위해 Cascade와 Fetch 전략을 신중히 선택.
'spring' 카테고리의 다른 글
[Spring] Jackson (0) | 2024.12.17 |
---|---|
[Spring] JWT기반 로그인 예시 (0) | 2024.12.11 |
[Spring] JPA (0) | 2024.12.03 |
[Spring] 프록시(proxy) (0) | 2024.11.30 |
[Spring] AOP 실제 적용 예시 (1) | 2024.11.29 |