상점과 상품 테이블 만들어서 연결하기

지금까지 독립된 엔티티와 테이블을 각각 만들었는데, 이번엔 그 둘을 연결지어보았다.

Store라는 엔티티가 Product라는 엔티티와 연결되어 한 개의 상점이 여러 개의 상품과, 한 개의 상품이 한 개의 상점과 연결되어있는 관계를 설정하고자 했다.

OneToMany, ManyToOne

일대다, 다대일. 이름만 봐도 각각 Store와 Product에 대한 속성으로 딱인 듯 싶다.

각 어노테이션은 단방향 관계를 설정할 수 있으며, 내가 원하는 양방향 관계를 설정하기 위해선 연결될 두 엔티티에 각각 관계에 맞는 어노테이션을 붙여 주면 된다.

class Store {
    ...

    @OneToMany
    private List<Product> products;
}

class Product {
    ...

    @ManyToOne
    private Store store;
}

양방향 매핑시 주종관계 구별하기

상점 -> 상품
상점 <- 상품

이 상태에서 객체 간의 연관관계를 관리하는 곳은 두 곳이다. 각각 상품, 상점. 외래키는 하나인 상태에서, 참조는 두 군데에서 일어나는 모순이 일어난다. 이런 상황을 해결하기 위해 JPA는 두 객체의 주종관계를 명시해 외래키를 어디서 관리할지 설정한다.

외래키를 관리하는 ‘주인’은 외래키의 삽입, 삭제, 수정을 관리할 수 있으나, 주인이 아닌 쪽은 읽기만 가능하다. 이 ‘주인’ 설정은 mappedBy로 설정할 수 있다.

mappedBy

mappedBy를 사용해 외래키 관리자, 즉 주인을 설정하게 되는데, 이는 서비스에 따라 다르다. 내 상태에서는 상점이 그 주인이 되는게 타당하다. 상점에 대해 상품을 등록하고, 삭제하고, 수정하는게 용이하지 상품에 대한 상점을 바꾸는 것은 비효율적인 상황이 일어날 수 있기 때문이다.

class Store {
    ...

    @OneToMany(mappedBy = "store")
    private List<Product> products;
}

@JoinColumn

양방향 연관관계 설정을 할 때 주인이 @OneToMany에는 mappedBy를, @ManyToOne에는 @JoinColumn이 추가되어있는 코드를 많이 접했다.

@JoinColumn은 mappedBy처럼 항상 써야하는걸까?

이 어노테이션은 엔티티간 join과 관계 없이 외래키 이름을 명시하기 위해 사용되는 어노테이션처럼 보인다. 이에 대한 의문을 가진 멋진 블로그 글을 참고했다.

결론

어렵다.

시험을 위한 암기 지식에 불과했던 내 정보처리기사 데이터베이스 지식은 휘발된지 오래… 외래키며 엔티티며 테이블이며…

API를 만들어내는것도 좋은데 관련된 데이터베이스 지식을 같이 가져가야 할 것 같다. 안그럼 나중에 데이터끼리 꼬일 것 같은 느낌..

JPA가 알아서 해주는게 많아서 객체간, 엔티티간 관계가 꼬이면 어떡하지 라는 생각을 많이 했는데, 역시 양방향 매핑시 무한루프가 발생하기도 한다고 한다. 이런 상황에 대비해 명시적으로 처리해주는 방식을 잘 배워놔야겠다.

댓글남기기