티스토리 뷰

jpa

[JPA] Entity 연관관계

구삼칠오 2022. 1. 6. 19:24

RDB는 외래키를 사용해 테이블 사이의 연관관계를 나타냅니다. 이 외래키는 RDB를 RDB('관계형' 데이터베이스)로 만들어 주는 아주 중요한 속성이죠. 따라서 JPA는 엔티티 사이에 연관관계를 매핑하는 방법을 제공합니다. 하지만 객체와 테이블의 차이로 인해 연관관계를 표현하는 방식 또한 차이가 있고 조금 복잡해지는 부분이 있는 것 같습니다.

테이블은 외래키로 연관관계를 맺습니다. 외래키 하나만으로 두 테이블 사이의 관계가 표현됩니다. 하지만 객체 사이의 관계는 테이블처럼 값으로 표현되지 않습니다. (물론 할 수는 있지만 oop스럽지 않죠) 객체 사이의 관계는 참조로 표현되죠. 따라서 JPA는 적절한 어노테이션만 달아준다면 참조로 표현된 객체 사이의 관계를 테이블 사이의 관계로 매핑해 줍니다.

 

 

관계 설정 어노테이션

@OneToOne - 1:1 관계 매핑

@OneToMany - 1:n 관계 매핑

@ManyToOne - n:1 관계 매핑

@ManyToMany - n:n 관계 매핑

 

이 네 가지 어노테이션을 사용해서 모든 유형의 관계를 표현할 수 있습니다. 예를 들어 교실과 학생이 1:n의 관계를 맺고 있다고 한다면 아래와 같이 표현할 수 있는 것입니다. 아래와 같은 코드를 JPA는 Student 테이블에 ClassRoom의 id를 외래키로 연결하는 형태로 매핑해줄 것입니다.

@Entity
class ClassRoom {
    @Id
    private Long id;
}

@Entity
class Student {
    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn(name: "class_room_id") //조인을 위한 컬럼을 지정하는 어노테이션. name값의 이름으로 외래키가 생성된다.
    private ClassRoom classRoom;
}

 

이렇게 JPA를 사용하면 엔티티가 외래키를 갖는것이 아니라 관계를 맺고 있는 다른 엔티티의 참조를 갖고 있도록 설계할 수 있습니다.

 

 

 

양방향 연관관계와 연관관계 주인

이렇게 JPA를 활용하면 엔티티를 OOP스럽게 유지하면서 테이블 사이의 관계를 표현할 수 있습니다. 하지만 아직 테이블과의 간극이 완전히 없어진 것은 아닙니다. 테이블은 외래키 하나만으로 양방향의 관계를 맺습니다. JOIN을 사용한다면 교실을 통해 학생에 접근할 수도, 학생을 통해 교실에 접근할 수도 있죠. 하지만 앞선 예제를 보면 학생은 교실에 대한 참조를 가지고 있지만, 교실은 학생에 대한 참조가 없어, OOP스러운 접근이 불가능합니다.

교실을 통해서도 학생으로 접근이 가능하기 위해선 교실 또한 학생에 대한 참조를 가지고 있어야 하며 이를 양방향 연관관계라고 합니다. (양방향 연관관계라고 부르지만 사실상 두 개의 단방향 연관관계)

@Entity
class ClassRoom {
    @Id
    private Long id;
    
    @OneToMany(mappedBy = "classRoom") //mappedBy엔 연관관계 주인인 필드가 들어간다.
    private List<Student> students = new ArrayList<>();
}

@Entity
class Student {
    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn(name: "class_room_id")
    private ClassRoom classRoom;
}

이 때 주의해야 할 점은 JPA스펙은 두 엔티티가 연관관계를 가질 때 둘 중 한 엔티티에서만 본인과 연관이 있는 엔티티의 영향을 미치고 수정을 할 수 있도록 제한하고 있다는 것입니다. 이때 전자의 엔티티가 연관관계 주인이 된다고 표현합니다.

 

ClassRoom의 student에 붙어있는 @OneToMany의 mappedBy는 연관관계의 주인이 아닌 필드에 붙는 값이며 그 안엔 연관관계의 주인이 되는 필드가 들어갑니다. JPA의 스펙대로 연관관계의 주인이 아닌 ClassRoom students는 read only로서 객체를 수정하더라도 DB에 반영이 되진 않습니다.

 

또 한가지 눈여겨 볼점은 1:n 중에 n쪽인 Student가 연관관계 주인으로 설정되어 있다는 것입니다. 직관적으로 생각했을 땐 ClassRoom이 주인이 되어 Student를 관리해야 할 것 같지만, 외래키를 가지고 있는 쪽이 연관관계의 주인이 되는 것이 낫습니다. ClassRoom이 주인이 될 경우 성능 이슈가 생길 수도 있고, 유지보수의 용의성 또한 떨어지게 됩니다.

 

 

 

ref.

자바 ORM 표준 JPA 프로그래밍 - 기본편

자바 ORM 표준 JPA 프로그래밍

'jpa' 카테고리의 다른 글

[JPA] @Entity(엔티티 매핑)  (0) 2021.12.24
[JPA] JPA와 영속성 컨텍스트(Persistence Context)에 대해  (0) 2021.12.01
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함