JPA

[JPA] 다양한 연관관계 매핑

리승자이 2022. 8. 4. 22:15
728x90

깃허브 바로가기
엔티티 연관관계를 매핑할때는 다음 3가지를 고려해야 한다.

  • 다중성
    • 다대일(@ManyToOne)
    • 일대다(@OneToMany)
    • 일대일(@OneToOne)
    • 다대다(@ManyToMany)
  • 단방향, 양방향
    • 테이블은 외래키 하나로 조인을 사용하여 양방향 쿼리가 가능한데 비해, 객체는 참조용 필드를 가지고 있어야만 연관된 객체 조회가 가능하다. 한쪽만 참조하는것이 단방향, 양쪽 서로 참조하는 것이 양방향이다.
  • 연관관계의 주인
    • 연관관계의 주인은 외래키 관리자이고, fk를 소유하고 있는 테이블을 기준으로 관리자 역할을 주면 된다고 생각한다.

다대일

다대일 관계의 반대 방향은 항상 일대다 관계이고 일대다 관계의 반대 방향은 항상 다대일 관계이다.
DB테이블의 1, N 관계에서 외래 키는 항상 N쪽에 있다.
따라서 객체의 양방향 관계에서 연관관계의 주인은 항상 N쪽이다.

다대일 양방향관계

양방향은 외래 키가 있는 쪽이 연관관계의 주인이다.

아까도 말했듯이 1:N, N:1 연관관계는 항상 N에 외래 키가 있다.

양방향 연관관계는 항상 서로를 참조해야 한다.

양방향 연관관계는 항상 서로 참조해야 한다. 어느 한쪽만 하게되는 순간 양방향 연관관계는 성립되지 않는다.
편의 메소드는 한곳에만 작성하거나 양쪽에 작성을 할 수가 있는데 양쪽에 다 작성하게 되면 무한루프에 빠지므로 주의해야 한다.

일대다

다대일 관계의 반대 방향이다. 일대다 관계는 엔티티를 하나 이상 참조할 수가 있으므로 Java Collection중 Collection, List, Set, Map 중에 하나를 사용해야 한다.

일대다 단방향

하나의 팀은 여러 멤버를 참조할 수 있는데 이런 관계를 일대다 관계라고 한다. 팀은 멤버를 참조하지만 멤버는 팀을 참조하지 않으면 둘의 관계는 단방향이다.

일대다 단방향 매핑의 단점

일대다 단방향 매핑의 단점은 매핑한 객체가 관리하는 외래 키가 다른 테이블에 있다는 점이다.
본인 테이블에 외래 키가 있으면 엔티티의 저장과 연관관계 처리를 INSERT 한번으로 끝낼 수가 있지만, 다른 테이블에 외래키가 존재한다면 연관관계 처리를 위한 UPDATE SQL을 추가로 실행해야 한다.

일대일

일대일 관계는 양쪽이 서로 하나의 관계만 갖는다.

일대일 관계의 특징

  • 일대일 관계는 그 반대도 일대일 관계
  • 테이블 관계에서 일대다, 다대일은 항상 다쪽이 외래키를 가진다. 반면 일대일 관계는 주 테이블이나 대상 테이블 중 어느 곳이나 외래키를 가질 수 있다.
    • 주 테이블에 외래 키
      • 주 객체가 대상 객체를 참조하는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 참조함.
      • 장점 - 주 테이블이 외래 키를 가지고 있으므로 주 테이블만 확인해도 대상 테이블과 연관관계가 있는지 알 수 있다.
    • 대상 테이블에 외래 키
      • 전통적인 DB개발자들은 보통 대상 테이블에서 외래 키를 두는 것을 선호한다. 이 방법의 장점은 테이블 관계를 일대일에서 일대다로 변경할 때 테이블 구조를 그대로 유지할 수 있다.

주의할점❗️

프록시를 사용할 때 외래 키를 직접 관리하지 않는 일대일 관계는 지연 로딩으로 설정해도 즉시 로딩된다.

프록시에 해당하는 설명은 이후 포스팅에서 다루도록 하겠다.

다대다

관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다. 그래서 보통 다대다 관계를 일대다, 다대일 관계로 풀어내는 연결 테이블을 사용한다.
그런데 객체는 테이블과는 다르게 객체 2개로 다대다 관계를 만들 수 있다.

@ManyToMany@JoinTable 을 사용해서 연결 테이블을 바로 매핑한 것이다.

@JoinTable의 속성은 아래와 같다.

  • @JoinTable.name
    • 연결 테이블을 지정한다.
  • @JoinTable.joinColumns
    • 현재 방향인 회원과 매핑할 조인 컬럼 정보를 지정한다.
  • @JoinTable.inverseJoinColumns
    • 반대 방향인 상품과 매핑할 조인 컬럼 정보를 지정한다.

매핑의 한계와 극복(연결엔티티 사용)

@ManyToMany 를 사용하면 연결 테이블을 자동으로 처리해주므로 도메인 모델이 단순해지고 여러 가지로 편리하다.
연결 테이블에 컬럼을 추가하면 더 이상 @ManyToMany 를 사용할 수 없다.
다른 엔티티에는 추가한 컬럼들을 매핑할 수 없기 때문이다.

JPA에서 복합키를 사용하려면 별도의 식별자 클래스를 만들어야 한다. 그리고 엔티티에 @IdClass 를 사용해서 식별자 클래스를 지정하면 된다.
이 식별자 클래스의 특징은 다음과 같다.

  • 복합 키는 별도의 식별자 클래스로 만들어야 한다.
  • Serializable을 구현해야 한다.
  • equals와 hashCode 메소드를 구현해야 한다.
  • 기본 생성자가 있어야 한다.
  • 식별자 클래스는 public이어야 한다.
  • @IdClass 를 사용하는 방법 외에 @EmbeddedId 를 사용하는 방법도 있다.

식별관계

부모 테이블의 기본키를 받아서 자신의 기본키 + 외래 키로 사용하는 것을 데이터베이스 용어로 식별 관계라고 한다.

정리

다대일, 일대다, 일대일, 다대다 연관관계 매핑에 관해 살펴봤는데 다대다 연관관계는 사용하기엔 JPA가 다 알아서 처리해주므로 편리했지만 연결 테이블에 필드가 추가된다고 하면 더는 사용할 수 없어서
실무에서 사용하기엔 다대일 매핑이 훨씬 괜찮아 보였다.

728x90