본문 바로가기

java

Spring boot jpa 연관 관계 알아보기 @OneToMany,@ManyToOne 공부

jpa에서 연관관계 방향으로는 1.단방향 2.양방향으로 나눌 수 있습니다.

-단방향은 한쪽에서 다른 한쪽을 참조 하지 않으면 단방향이 됩니다.

-양방향은 서로 다른쪽을 참조하고 있을때 양방향 관계가 됩니다.

이는 데이터 베이스에서는 하나의 외래키로 조인을 하면 되므로 양방향 단방향이 의미가 없으나

객체에서는 한쪽이 다른한쪽을 참조를 하지 않는다면 단방향 양방향으로 나뉘게 됩니다.

예시를 보면

아래와 같이 Order enitiy에 Orderitem이 일대다 관계로 성립하고 있을때

데이터 베이스에서는 일대다 중에 다에 외래키를 지정하므로 (자식테이블에 fk키 지정)

Order객체와 OrderItem 객체도 위와 같이 관계를 지정해 주어야 합니다.

예제1 Order

@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {

    @Id @GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "member_id")
    private Member member;


    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();


    @OneToOne(fetch = LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    private LocalDateTime orderDate; //주문시간

    @Enumerated(EnumType.STRING)
    private OrderStatus status; //주문상태 [ORDER, CANCEL]

예시2. OrderItem

@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {

    @Id @GeneratedValue
    @Column(name = "order_item_id")
    private Long id;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "item_id")
    private Item item;


    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "order_id")
    private Order order;

    private int orderPrice; //주문 가격
    private int count; //주문 수량

*참조의 다중성은 @OneToMany,@OneToOne,@ManyToOne,@ManyToMany 로 나뉠수 있습니다.

-예제는 @OneToMany와 @ManyToOne을 다루겠습니다.

이때 Order의 OrderItem은 Order의 입장에서 OrderItem은 여러개가 될 수 있으므로

@OneToMany 어노테이션을 사용하게 됩니다.

//Order entity
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();

반대로 OrderItem의 입장에서는 하나의 Order에 여러개의 OrderItem이 생성될 수 있으므로

@ManyToOne 어노테이션을 사용하게 됩니다.

//OrderItem Entity
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "order_id")
private Order order;

이때 연관관계를 지정해 주기 위해 mappedBy를 사용하게 되는데 이는 연관관계의 주인 fk키가 있는 곳에 지정을 해주어야 합니다. (연관관계의 주인으로 지정되지 않으면 입력 수정 삭제가 불가하고 조회만 가능)

Order의 orderItmes 필드는 연관관계의 주인이 아니므로 mapped by 를 사용하여 매핑을 하여서 order를 연관관계 주인으로 지정해 줍니다.

반대로 OrderItem의 order필드에서는 JoinColumn에 name="order_id" 을 지정하여서 Order Entity의 id를 참조해 줍니다

이렇게 서로 다른 엔티티에서 참조를 하는 것을 양방향 참조라 하며

반대로 한쪽에서 다른 한쪽의 엔티티를 참조하지않아 정보를 알수 없으면 단방향 이라고 합니다.

예시1) 다대일 단방향 Order

@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {

    @Id @GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    아래의 매핑을 지워버리면 order에서는 orderitem을 참조할수 없어 다대일 단방향 참조가 됨
    //@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    //private List<OrderItem> orderItems = new ArrayList<>();


    @OneToOne(fetch = LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    private LocalDateTime orderDate; //주문시간

    @Enumerated(EnumType.STRING)
    private OrderStatus status; //주문상태 [ORDER, CANCEL]

예시2) 다대일 단방향 Order

@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {

    @Id @GeneratedValue
    @Column(name = "order_item_id")
    private Long id;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "item_id")
    private Item item;


    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "order_id")
    private Order order;

    private int orderPrice; //주문 가격
    private int count; //주문 수량

위처럼 Order에서 orderitem필드를 지워버리면 orderitem 엔티티를 참조하지 않으므로 orderitem엔티티가 order엔티티를 참조하는 다대일 단방향 관계가 성립 됩니다.

이처럼 한쪽만 참조하는 관계를 단방향 관계라고 합니다.