[JPA] 연관관계 매핑 - N:1, 1:N

Bam·2025년 5월 18일
0

Spring

목록 보기
57/73
post-thumbnail

다중성

연관관계에는 다음과 같은 다중성들이 있습니다.

  • 다대일(N:1) ManyToOne
  • 일대다(1:N) OneToMany
  • 일대일(1:1) OneToOne
  • 다대다(M:N) ManyToMany

다대일의 반대는 일대다,
일대일의 반대는 일대일,
다대다의 반대는 다대다입니다.

지난 포스트에서 단방향, 양방향 연관관계에 대해서 설명을 했으니 이번에는 다중성들을 기준으로 연관관계를 설명해볼까 합니다.


다대일(N:1) ManyToOne

다시 한 번 이야기 하지만 다대일의 반대는 항상 일대다입니다. (반대도 마찬가지) 또한 이들 관계에서 연관관계의 주인은 항상 다(N)쪽에 있습니다.

단방향 다대일

@Entity
@Table(name = "customers_table")
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "c_id", nullable = false)
    private Long id;

    @Column(name = "name", nullable = false, length = 100)
    private String name;
    
    //생성자 및 getter
}
@Entity
@Table(name = "orders_table")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "o_id", nullable = false)
    private Long id;

    @Column(name = "order_date", nullable = false)
    private LocalDateTime orderDate;

    @ManyToOne(fetch = FetchType.LAZY)	//단방향
    @JoinColumn(name = "c_id", nullable = false)
    private Customer customer;
    
    //생성자 및 getter
}

주문 대 고객 다대일(N:1, 주문:고객) 단방향 다대일 연관관계입니다. 연관관계의 주인인 Order는 상대인 Customer 참조 필드를 가지고 있으나 CustomerOrder 참조 필드를 가지고 있지 않습니다.

양방향 다대일

@Entity
@Table(name = "customers_table")
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "c_id", nullable = false)
    private Long id;

    @Column(name = "name", nullable = false, length = 100)
    private String name;
    
    /**
     * 양방향 @OneToMany 
     * Order엔 @ManyToOne Customer 매핑
     */
    @OneToMany(mappedBy = "customer")
    private Order order;
    
    //생성자 및 getter
}
@Entity
@Table(name = "orders_table")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "o_id", nullable = false)
    private Long id;

    @Column(name = "order_date", nullable = false)
    private LocalDateTime orderDate;

    @ManyToOne(fetch = FetchType.LAZY)	//단방향
    @JoinColumn(name = "c_id", nullable = false)
    private Customer customer;
    
    //생성자 및 getter
}

주문 대 고객 다대일(N:1, 주문:고객) 양방향 다대일 연관관계입니다. OrderCustomer가 서로 참조를 하고 있습니다.


일대다(1:N) OneToMany

일대다 연관관계는 조금 다른 방식으로 매핑이 됩니다. 기존엔 를 기준으로 매핑을 해서 단일 필드만을 사용했지만, 일대다는 하나인 쪽인 다수인 쪽을 매핑하기 때문에 자바 컬렉션을 이용해서 필드를 선언하게 됩니다.

단방향 일대다


@Entity
@Table(name = "customers_table")
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "c_id", nullable = false)
    private Long id;

    @Column(name = "name", nullable = false, length = 100)
    private String name;

    /**
     * 단방향 1:N 매핑
     * - Customer(1) → Order(N)
     * - orders_table 에 FOREIGN KEY(c_id) 컬럼이 생성된다.
     */
    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "c_id", nullable = false)
    private List<Order> orders = new ArrayList<>();
    
    //생성자 및 getter
}
@Entity
@Table(name = "orders_table")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "o_id", nullable = false)
    private Long id;

    @Column(name = "order_date", nullable = false)
    private LocalDateTime orderDate;
    
    //생성자 및 getter
}

(주인이 아닌)일 쪽이 다 쪽인 Order의 참조 정보를 가지고 있기 때문에 컬렉션(List)를 통해서 Order의 키를 저장합니다. 다 쪽은 하나가 아니라 여러 개 일수도 있기 때문에 반드시 컬렉션을 통해 저장해야합니다.

일대다 단방향 연관관계의 경우 테이블에 외래 키가 다 쪽에 저장되어 있기 때문에 Order가 추가되면 별도로 Customer의 필드를 추가적으로 UPDATE 해야하는 추가 작업이 발생한다는 단점이 있습니다.

따라서 가능하다면 대부분의 상황에서는 다대일 양방향 연관관계 매핑의 사용이 권장됩니다.

양방향 일대다

양방향 일대다 연관관계 매핑이라는 개념은 존재하지 않습니다. 왜냐하면 다대일 양방향 연관관계의 반대이기 때문에 두 개가 똑같은 개념이기 때문입니다.

따라서 이 부분은 위의 양방향 다대일이나 양방향 연관관계 포스트를 통해 이해하시면 됩니다.

0개의 댓글