@OneToMany, @ManyToOne 관계

JPA에서 @OneToMany@ManyToOne객체 간의 관계를 맵핑하는 어노테이션으로, 1:N(일대다) 관계N:1(다대일) 관계를 정의할 때 사용됩니다.


1. @ManyToOne (N:1 관계)

여러 개의 엔티티가 하나의 엔티티를 참조하는 관계입니다.
이 경우, 외래 키(FK)는 다(N)의 테이블이 갖습니다.

예제: Order(N)Member(1)

  • 한 명의 회원(Member)은 여러 개의 주문(Order)을 가질 수 있습니다.
  • 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;
}

SQL 테이블 구조

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)
);

2. @OneToMany (1:N 관계)

하나의 엔티티가 여러 개의 엔티티를 포함하는 관계입니다.
외래 키(FK)는 반대쪽(@ManyToOne이 있는 테이블)이 가집니다.

예제: Member(1)Order(N)

  • 한 명의 회원(Member)이 여러 개의 주문(Order)을 가질 수 있습니다.
  • 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 단독으로 사용하면 성능 이슈 발생 가능
    • JPA는 연관된 엔티티를 조회할 때 즉시 로딩(Eager Loading) 기본 설정을 합니다.
    • 따라서 @OneToMany를 사용할 때는 지연 로딩(Lazy Loading) 설정을 추천합니다.
      @OneToMany(mappedBy = "member", fetch = FetchType.LAZY)
  • mappedBy를 반드시 설정해야 함
    • @OneToMany는 연관된 @ManyToOne 필드를 mappedBy로 설정해야 합니다.
    • mappedBy를 설정하지 않으면 양방향 관계에서 외래 키를 중복 생성하는 문제가 발생할 수 있습니다.

3. @OneToMany vs. @ManyToOne 요약

관계 유형어노테이션외래 키 위치mappedBy 필요 여부특징
다대일(N:1)@ManyToOne다(N) 테이블에 FK 저장❌ 없음외래 키를 직접 관리
일대다(1:N)@OneToMany다(N) 테이블에 FK 저장✅ 필수외래 키를 @ManyToOne 쪽에서 관리

4. 양방향 관계 설정 (추천 방식)

보통 @ManyToOne을 FK의 주인으로 설정하고,
@OneToManymappedBy를 사용해 읽기 전용으로 설정하는 것이 좋습니다.

@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 리스트를 읽기 전용으로 설정하여 불필요한 쿼리를 방지합니다.

5. 정리

  • @ManyToOne: N:1 관계로, FK를 직접 관리하는 엔티티에 사용 (필수)
  • @OneToMany(mappedBy = "xxx"): 1:N 관계에서 반대쪽(@ManyToOne) 필드와 매핑 (보조 역할)
  • 최적화:
    • @OneToManyLazy Loading 설정 필수
    • @ManyToOneFK를 관리하는 것이 일반적이며, 단방향 관계도 가능

JPA에서 연관 관계를 올바르게 설정하려면 @ManyToOne을 중심으로 설계하는 것이 일반적입니다. 🚀

profile
AI 답변 글을 주로 올립니다.

0개의 댓글