본문 바로가기
JPA & Hibernate

JPA 다양한 연관관계 매핑

by Salt-Fn 2023. 2. 27.

인프런의 자바 ORA 표준 JPA 프로그래밍 - 기본편과 자바 ORM 표준 JPA 책을 공부하며 정리한 포스트입니다.

 

 엔티티의 연관관계를 매핑할 때는 두 엔티티가 일대일 관계인지 일대다 관계인지 다중성을 고려해야 한다. 그리고 한쪽만 참조하는 단방향 관계인지 서로 참조하는 양방향 관계인지 고려해야 한다. 마지막으로 양방향 관계면 연관관계의 주인을 정해야 한다.

다중성

  • 다대일 (@ManyToOne)
  • 일대다 (@OneToMany)
  • 일대일 (@OneToOne)
  • 다대다 (@ManyToMany)

연관관계의 주인

JPA는 두 객체 연관관계 중 하나를 정해서 데이터베이스 외래 키를 관리하는데 이것을 연관관계의 주인이라 한다. 외래키를 가진 테이블과 매핑한 엔티티가 외래키를 관리하는게 효율적이므로 보통 이곳을 연관관계의 주인으로 선택한다. 주인이 아닌 방향은 외래 키를 변경할 수 없고 읽기만 가능하다. 연관관계의 주인이 아닌 쪽에 mappedBy 속성을 사용하고 연관관계의 주인 필드 이름을 값으로 입력해야 한다.

다대일

다대일 단방향

데이터베이스 테이블의 일(1), 다(N) 관계에서 외래 키는 항상 다쪽에 있다. 따라서 객체 양방향 관계에서 연관관계의 주인은 항상 다쪽이다.

다대일 양방향

  • 양방향은 외래 키가 있는 쪽이 연관관계의 주인이다.
  • 양방향 연관관계는 항상 서로를 참조해야 한다.
    어느 한 쪽만 참조하면 양방향 연관관계가 성립하지 않는다. 항상 서로 참조하게 하려면 연관관계 편의 메소드를 작성하는 것이 좋은데 회원의 setTeam(), 팀의 addMember() 메소드가 편의 메소드들이다. 편의 메소드는 한 곳에만 작성하거나 양쪽 다 작성할 수 있는데, 양쪽에 다 작성하면 무한루프에 빠지므로 주의해야 한다.

일대다

일대다 관게는 엔티티를 하나 이상 참조할 수 있으므로 자바 컬렉션인 Collection, List, Set, Map 중에 하나를 사용 해야 한다.

일대다 단방향(JPA 2.0부터 지원)

보통 자신이 매핑한 테이블의 외래 키를 관리하는데, 이 매핑은 반대쪽 테이블에 있는 외래 키를 관리한다. 일대다 관게에서 외래 키는 항상 다쪽 테이블에 있다. 따라서 반대편 테이블의 외래 키를 관리하는 특이한 모습이 나타난다. 일대다 단방향 관계를 미팽할 때는 @JoinColumn을 명시해야 한다. 그렇지 않으면 JPA는 연결 테이블을 중간에 두고 연관관계를 관리하는 조인 테이블 전략을 기본으로 사용해서 매핑한다.

일대다 단방향 매핑의 단점

매핑한 객체가 관리하는 외래 키가 다른 테이블에 있다는 것이 단점이다. 본인 테이블에 외래 키가 있으면 엔티티의 저장과 연관관계 처리를 insert sql 한 번으로 끝낼 수 있지만, 다른 테이블에 외래 키가 있으면 연관관계 처리를 위한 update sql 을 추가로 실행해야 한다.

일대다 단방향 매핑보다는 다애일 양방향 매핑을 사용하자

일대다 단방향 매핑을 사용하면 엔티티를 매핑한 테이블이 아닌 다른 테이블의 외래키를 관리해야 해서 성능 문제도 있지만 관리도 부담스럽다. 좋은 방법은 일대다 단방향 매핑 대신에 다대일 양방향 매핑을 사용하는 것이다.

일대다 양방향

일대다 양방향 매핑은 존재하지 않는다. 대신 다대일 양방향 매핑을 사용해야 한다.  양방향 매핑에서 @OneToMany는 연관관계의 주인이 될 수 없다. 항상 다 쪽에 외래 키가 있기 때문에 @OneToMany, @ManyToOne 둘 중에 연관관계의 주인은 항상 다쪽인 @ManyToOne을 사용하는 곳이다. 이런 이유로 @ManyToOne 에는 mappedBy 속성이 없다.

일대일

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

  • 일대일 관계는 반대도 일대일 관계다.
  • 테이블 관계에서 일대다, 다대일은 항상 다쪽이 외래키를 가진다. 반면에 일대일 관계는 주 테이블이나 대상 테이블 둘 중 어느 곳이나 외래 키를 가질 수 있다.
  1. 주 테이블에 외래 키
    JPA도 주 테이블에 외래 키가 있으면 좀 더 편리하게 매핑할 수 있다.
  2. 대상 테이블에 외래 키
    일대일 관계 중 대상 테이블에 외래 키가 있는 단방향 관계는 JPA에서 지원하지 않는다.
    일대일 매핑에서 대상 테이블에 외래 키를 두고 싶으면 이렇게 양방향으로 매핑한다.

다대다

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

 

단방향

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

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

양방향

다대다 매핑이므로 역방향도 @ManyToMany를 사용한다. 그리고 양쪽 중 원하는 곳에 mappedBy로 연관관계의 주인을 지정한다. 양방향 연관관계는 연관관계 편의 메소드를 추가해서 관리하는 것이 편리하다.

복합 기본 키

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

 

복합키를 위한 식별자 클래스의 특징

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

식별 관계

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

'JPA & Hibernate' 카테고리의 다른 글

JPA 프록시와 연관관계 관리  (0) 2023.03.06
JPA 고급 매핑  (0) 2023.03.03
JPA 연관관계 매핑 기초  (0) 2023.02.23
JPA 엔티티 매핑  (0) 2023.02.22
JPA 영속성 관리  (0) 2023.02.20