1. 연관관계 매핑 소개
- 연관관계 매핑이란 객체의 참조와 테이블의 외래 키를 매핑하는 작업입니다.
- 객체와 테이블은 연관관계를 맺는 방식에 근본적인 차이가 있습니다
- 객체는 참조(주소)로 연관관계를 맺으며, 이는 항상 단방향입니다.
- 테이블은 외래 키로 연관관계를 맺으며, 이는 항상 양방향입니다.
- 이러한 차이를 이해하고 효과적으로 매핑하는 방법을 알아보겠습니다.
2. 연관관계 매핑 시 고려사항
- 연관관계를 매핑할 때는 다음 세 가지를 고려해야 합니다
- 다중성
- 방향
- 연관관계의 주인
2.1 다중성
- 다중성은 엔티티 간의 관계가 몇 대 몇인지를 나타냅니다.
- 연관관계 매핑 시 다중성을 나타내는 어노테이션은 필수적으로 사용해야 합니다.
- 다중성의 종류:
- 다대일(
@ManyToOne
) - 일대다(
@OneToMany
) - 일대일(
@OneToOne
) - 다대다(
@ManyToMany
)
- 다대일(
2.1.1 @ManyToOne
- 다대일 관계를 나타내는 매핑 정보입니다.
- 가장 많 이 사용하는 연관관계입니다.
속성 | 설명 | 기본값 |
---|---|---|
optional | false로 설정하면 연관된 엔티티가 항상 있어야 합니다. | TRUE |
fetch | 글로벌 페치 전략을 설정합니다. | FetchType.EAGER |
cascade | 영속성 전이 기능을 사용합니다. | |
targetEntity | 연관된 엔티티의 타입 정보를 설정합니다. 이 기능은 거의 사용하지 않습니다. 컬렉션을 사용해도 제네릭으로 타입 정보를 알 수 있습니다. |
2.1.2 @OneToMany
- 일대다 관계를 나타내는 매핑 정보입니다.
- 양방향 매핑에서 주로 사용합니다.
경고
일대다 단방향 매핑 사용 시 주의사항
- 일이 연관관계의 주인인 경우, 엔티티가 관리하는 외래 키가 다른 테이블에 있게 됩니다.
- 연관관계 관리를 위해 추가로 UPDATE SQL이 실행됩니다.
- 일대다 단방향보다는 다대일 양방향 매핑을 사용하는 것이 좋습니다.
- @JoinColumn을 꼭 사용해야 합니다. 그렇지 않으면 조인 테이블 방식을 사용하게 됩니다.
속성 | 설명 | 기본값 |
---|---|---|
mappedBy | 연관관계의 주인 필드의 이름을 값으로 지정해야 합니다. | |
fetch | 글로벌 페치 전략을 설정합니다. | FetchType.LAZY |
cascade | 영속성 전이 기능을 사용합니다. | |
targetEntity | 연관된 엔티티의 타입 정보를 설정합니다. 이 기능은 거의 사용하지 않습니다. 컬렉션을 사용해도 제네릭으로 타입 정보를 알 수 있습니다. |
2.1.3 @OneToOne
- 일대일 관계를 나타내는 매핑 정보입니다.
- 주 테이블이나 대상 테이블 중 하나에 외래 키를 설정합니다.
- 다대일 양방향 매핑처럼 외래 키가 있는 곳이 연관관계의 주인입니다.
- 주인이 아닌 곳은 mappedBy 속성을 적용합니다.
주 테이블에 외래 키를 설정하는 경우
- 주 객체가 대상 객체의 참조를 가지는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾습니다.
- 객체지향 개발자가 선호하는 방식입니다.
- JPA 매핑이 편리합니다.
- 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인이 가능합니다.
- 값이 없으면 외래 키에 null을 허용해야 합니다.
대상 테이블에 외래 키를 설정하는 경우
- 대상 테이블에 외래 키가 존재합니다.
- 전통적인 데이터베이스 개발자가 선호하는 방식입니다.
- 주 테이블에 외래 키를 설정하는 것과 달리 null을 허용하지 않아도 됩니다.
- 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조를 그대로 유지할 수 있습니다.
정보
지연 로딩의 한계 대상 테이블에 외래 키가 있는 경우, 연관관계의 주인이 아닌 엔티티를 조회할 때 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됩니다.
예를 들어:
- 멤버와 락커 테이블이 존재하고, 대상 테이블인 락커에 외래키가 있다면(락커가 연관관계의 주인)
- 멤버를 조회할 때(연관관계의 주인이 아닌 엔티티)
- 멤버 테이블만 조회해서는 락커를 같이 조회할 수 없어 락커 테이블을 추가로 조회하는 쿼리가 필요합니다.
- 따라서 지연 로딩으로 설정해도 즉시 로딩처럼 쿼리가 발생하게 됩니다.
경고
단방향 관계 제한 대상 테이블에 외래 키가 있는 단방향 관계는 JPA가 지원하지 않습니다. 따라서 일대일 매핑에서 대상 테이블에 외래 키를 두고 싶으면 양방향으로 매핑해야 합니다.
2.1.4 @ManyToMany
- 다대다 관계를 나타내는 매핑 정보입니다.
- 관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없습니다.
- 연결 테이블을 사용해서 일대다, 다대일 관계로 풀어내야 합니다.
@JoinTable
로 연결 테이블을 지정합니다.
위험
실무에서는 @ManyToMany를 사용하지 않습니다.
- 연결 테이블을 엔티티로 승격시켜 다대다 관계를 일대다, 다대일 관계로 풀어내는 것이 좋습니다.
- 이렇게 하면 추가 정보를 넣을 수 있고 더 유연한 설계가 가능합니다.
다대다 연관관계 구현 방법
다대다 관계를 일대다, 다대일 관계로 풀어내기 위해 연결 테이블을 만들 때 식별자를 구성하는 방법:
- 식별 관계: 받아온 식별자를 기본키 + 외래 키로 사용
- 비식별 관계: 받아온 식별자를 외래 키로만 사용하고 새로운 식별자를 추가
팁
비식별 관계를 사용하면 복합 키를 위한 식별자 클래스를 만들지 않아도 되므로 편리하게 ORM 매핑을 할 수 있습니다. 따라서 비식별 관계를 추천합니다.
2.2 방향
연관관계는 방향에 따라 단방향과 양방향으로 나눌 수 있습니다.