연관관계 매핑시 고려사항 3가지
- 다중성
- 단방향, 양방향
- 연관관계의 주인
다중성
- 다대일 - @ManyToOne
- 일대다 - @OneToMany
- 일대일 - @OneToOne
- 다대다 - @ManyToMany
대칭성을 지니고 있기에, 매핑 시 반대편으로도 생각해볼 수 있도록 하자
단방향 과 양방향
테이블
외래키 하나로 양쪽 조인 가능
사실상 방향이란 개념이 없다.
객체
참조용 필드가 있는 쪽으로만 참조 가능
- 한쪽만 참조하면 단방향
- 양쪽이 서로 참조하면 양방향
객체의 경우 참조가 있어야만 조회가 가능하다
연관관계의 주인
테이블의 경우 외래키 하나로 두 테이블이 연관관계를 맺지만,
객체의 경우 각각 단방향으로 참조를 하기 때문에 양방향 (단방향 2개)을 가지게 된다.
이러한 이유로 둘 중 테이블의 외래키를 관리할 곳을 지정해야함
해당 참조가 바로 연관관계의 주인이 된다.
반대의 경우 외래키에 영향을 주지 않으며, 단순 조회 용도로만 사용 가능하다.
다대일 [N : 1]
관계형 디비에서는 "다" 쪽이 외래키를 가지게 된다.
그리고 객체 매핑 시 해당 객체에 다대일 연관관계 매핑을 해주면 된다. @ManyToOne
반대편 객체 참조가 필요 시 - 다대일 양방향
반대편 객체에 컬렉션을 선언하여 연관관계 매핑을 해주면 된다. - @OneToMany(mappedBy = "")
반드시 단순 조회 용도로만 사용한다는 의미로 mappedBy 를 적어주자
일대다 [1 : N]
일대다 단방향은 일대다 에서 일(1)이 연관관계의 주인이 되는 것이다. @OneToMany + @JoinColumn
그렇지만 테이블 일대다 관계는 항상 다(N) 쪽에 외래키가 있다.
이러한 차이점 때문에 반대편 테이블의 외래키를 관리하는 특이한 구조 (권장하지 않음)
엔티티가 관리하는 외래키가 다른 테이블에 존재한다.
반대편에 존재하는 외래키를 수정하기 위해 update 쿼리가 하나 더 발생된다.
※ 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자
일대다 양방향 반대편 (외래키 존재하는 엔티티) 에 @ManyToOne @JoinColumn(insertable=false, updatable=false) 작성
반드시 읽기 전용(연관관계 주인이 아닌 것을 명시)으로 해주기 위해 insertable=false, updatable=false 속성을 작성해줘야 한다.
일대일 [1 : 1]
일대일 관계는 그 반대도 일대일 (대칭적)
이러한 경우에는 어느 곳에서든 연관관계 주인이 될 수 있다. (주 테이블 : 대상 테이블 모두 외래키 선택 가능)
외래키에 데이터베이스 유니크 제약조건 추가
일대일 - 주 테이블에 외래키 단방향
예시로는 멤버와 락커 (일대일 관계) 중 멤버에 락커의 ID 외래키를 관리하는 경우
다대일 단방향 매핑과 유사함
일대일 - 주 테이블에 외래키 양방향
다대일 양방향 처럼 반대편에 @OneTOne(mappedBy = "") 작성해주면 된다.
일대일 - 대상 테이블 외래키 단방향의 경우 지원되지 않는다.
일대일 - 대상 테이블 외래키 양방향의 경우 주 테이블 외래키 양방향과 같다.
일대일 연관관계의 주인 설정
주 테이블에 외래키
- 주 객체가 대상 객체의 참조를 가지는 것 처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾음
- 객체지향 개발자 선호
- JPA 매핑 편리
- 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
- 단점: 값이 없으면 외래키에 null 허용
대상 테이블에 외래키
- 대상 테이블에 외래 키가 존재
- 전통적인 데이터베이스 개발자 선호
- 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
- 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨(JPA 프록시 연관)
다대다 [N : M]
실제 실무에서 사용하지 않는다.
실제로는 연결 테이블이 생성되어 관리되는 것이다. (테이블은 다대다를 표현할 수 없음)
@ManyToMany, @JoinTable 로 연결 테이블 지정 가능
다대다 한계
연결 테이블이 생길 뿐더러 해당 테이블이 단순히 연결만 하고 끝나지 않음
해당 테이블에 추가적인 데이터들이 들어올 수 있다.
다대다 한계 극복
@ManyToMany → @ManyToOne, @OneToMany
연결 테이블용 엔티티 추가 (연결 테이블을 엔티티로 승격)
참조
- 해당 게시글은 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 바탕으로 작성되었습니다.
댓글