연관관계 매핑시 고려해야할 사항은 크게 3가지이다.
하나씩 알아보자.
다중성은 4가지가 있다.
@ManyToOne
@OneToMany
@OneToOne
@ManyToMany
DB의 다중성을 기준으로 어노테이션을 고르면 된다. 애매하면 반대쪽을 생각하자!
(일대일의 반대는 일대일 다대일의 반대는 일대다, 이들은 대칭성이 존재한다.)
사실, 다대다는 실무에서 절대 사용을 하지 않는다.
가장 많이사용하는 것은 다대일, 일대다 이다. 일대일도 가끔은 나온다.
하나씩 자세히 알아보자.
다가 연관관계의 주인이다. 따라서, 다에 FK가 가야한다. RDB의 관점에서 보면 이렇게 해야 설계에 유리하다.
단방향 양뱡향은 테이블 설계에 영향을 주지 않는다.
양방향으로 하기 위해선 객체의 설계를 다르게 하면 된다. 단순히 코드만 추가하면 된다는 뜻이다.
@JoinColumn
을 꼭 사용해야 한다. 그렇지 않으면 조인 테이블 방식을 사용한다.(중간에 테이블을 하나 추가함)@JoinColumn(insertable=false, updatable=false)
을 사용하면 된다.그러나, 일대다는 엔티티가 관리하는 외래 키가 다른 테이블에 있고 연관관계 관리를 위해 추가로 UPDATE SQL 실행하므로 성능상 손해가 존재한다.
하지만, 안쓰는 가장 큰 이유는 작성한 코드와 쿼리의 차이로 인해 혼란을 야기한다는 점이다.
(난 분명 Team
객체 관련 코드만 작성했는데 Member
쿼리가 나가면 당황스러울것이다...)
따라서, 실무에서 이러한 모델은 거의 사용하지 않는다.
일대일 관계는 그 반대도 일대일이므로 주 테이블이나 대상 테이블 둘 중 아무대나 FK를 넣어도 된다.
이 둘을 기준으로 나눠서 알아보자.
@ManyToOne
) 단방향 매핑과 유사하다.mappedBy
를 적용한다.참고
@JoinColumn(name = "")
name
값은 디폴트값이 매우 복잡하므로 직접 입력하자.
null
허용 일대일관계는 내 Entity에 있는 FK는 직접관리해야 한다.
일대일 관계에서 FK를 어떤 테이블에 적용해도 상관이 없지만 미래를 고려해보자.
비지니스 룰이 바뀌어서 일대일에서 일대다로 바뀌면 주 테이블에 FK가 있는게 대응하기가 쉽다.
반대로 다대일로 바뀌면 대상 테이블에 FK가 있는게 대응하기 쉽다.
실무에선 주 테이블에 FK를 두는게 더 낫다.
프록시 객체를 두면 JPA는 필드값이 있는지를 반드시 알아야 한다.
대상 테이블에 FK를 두면 어차피 조회할 때 값을 알고 있으므로 지연로딩이 의미가 없어진다.
RDB는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다. 연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야한다.
물론, 객체는 컬렉션을 사용해서 다대다 관계를 구현할 수 있다.
@ManyToMany
을 사용하면 되고 @JoinTable
로 연결 테이블을 지정한다. 또한, 단방향, 양방향 모두 가능하다.
편리해 보이지만 실무에서 절대 사용하지 않는다. 연결 테이블이 단순히 연결만 하고 끝나지 않는다.
다음과 같이 주문시간, 수량 같은 데이터가 들어올 수 있다.
참고
@JoinColumn(...)
FK 제약조건을 매핑하는 것이 아니라 FK를 매핑하는 것이다.
연결 테이블용 엔티티 추가(연결 테이블을 엔티티로 승격)함으로써 다대다 한계를 극복할 수 있다.
@ManyToMany
-> @OneToMany
, @ManyToOne
계속 언급하지만 객체의 양방향은 단방향이 2개가 있는 것이다.
이렇게 이해해야 연관관계의 주인을 확실히 이해할 수 있다.