JPA에서 @OneToMany와 @ManyToOne은 객체 간의 관계를 맵핑하는 어노테이션으로, 1:N(일대다) 관계와 N:1(다대일) 관계를 정의할 때 사용됩니다.
@ManyToOne (N:1 관계)여러 개의 엔티티가 하나의 엔티티를 참조하는 관계입니다.
이 경우, 외래 키(FK)는 다(N)의 테이블이 갖습니다.
Order(N) ↔ Member(1)Order 테이블에 member_id(외래 키)가 저장됩니다.@Entity
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToOne // 다(N) -> 하나(1) 관계
@JoinColumn(name = "member_id") // FK 컬럼 지정
private Member member;
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
}
CREATE TABLE Member (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
);
CREATE TABLE Order (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
member_id BIGINT,
FOREIGN KEY (member_id) REFERENCES Member(id)
);
@OneToMany (1:N 관계)하나의 엔티티가 여러 개의 엔티티를 포함하는 관계입니다.
외래 키(FK)는 반대쪽(@ManyToOne이 있는 테이블)이 가집니다.
Member(1) ↔ Order(N)Order 테이블에 member_id(외래 키)가 존재하기 때문에,@OneToMany 관계에서는 mappedBy를 사용하여 외래 키를 관리하는 엔티티를 지정해야 합니다.@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "member") // Order 엔티티의 "member" 필드에 의해 매핑됨
private List<Order> orders = new ArrayList<>();
}
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToOne // 다(N) -> 하나(1) 관계
@JoinColumn(name = "member_id")
private Member member;
}
@OneToMany 단독으로 사용하면 성능 이슈 발생 가능@OneToMany를 사용할 때는 지연 로딩(Lazy Loading) 설정을 추천합니다.@OneToMany(mappedBy = "member", fetch = FetchType.LAZY)mappedBy를 반드시 설정해야 함@OneToMany는 연관된 @ManyToOne 필드를 mappedBy로 설정해야 합니다. mappedBy를 설정하지 않으면 양방향 관계에서 외래 키를 중복 생성하는 문제가 발생할 수 있습니다.@OneToMany vs. @ManyToOne 요약| 관계 유형 | 어노테이션 | 외래 키 위치 | mappedBy 필요 여부 | 특징 |
|---|---|---|---|---|
| 다대일(N:1) | @ManyToOne | 다(N) 테이블에 FK 저장 | ❌ 없음 | 외래 키를 직접 관리 |
| 일대다(1:N) | @OneToMany | 다(N) 테이블에 FK 저장 | ✅ 필수 | 외래 키를 @ManyToOne 쪽에서 관리 |
보통 @ManyToOne을 FK의 주인으로 설정하고,
@OneToMany는 mappedBy를 사용해 읽기 전용으로 설정하는 것이 좋습니다.
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "member_id") // FK 직접 관리
private Member member;
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "member", fetch = FetchType.LAZY) // 읽기 전용 매핑
private List<Order> orders = new ArrayList<>();
}
Order 엔티티가 member_id 외래 키를 직접 관리하고,Member 엔티티는 Order 리스트를 읽기 전용으로 설정하여 불필요한 쿼리를 방지합니다.@ManyToOne: N:1 관계로, FK를 직접 관리하는 엔티티에 사용 (필수)@OneToMany(mappedBy = "xxx"): 1:N 관계에서 반대쪽(@ManyToOne) 필드와 매핑 (보조 역할)@OneToMany는 Lazy Loading 설정 필수@ManyToOne이 FK를 관리하는 것이 일반적이며, 단방향 관계도 가능JPA에서 연관 관계를 올바르게 설정하려면 @ManyToOne을 중심으로 설계하는 것이 일반적입니다. 🚀