본문 바로가기
개발

JPA 연관관계

by just다해 2024. 9. 18.
  • 방향(Direction) : 방향은 객체 관계에만 존재하며, 테이블 관계는 항상 양방향입니다.
    • 단방향 : 한쪽만 참조하는 것
    • 양방향 : 양쪽 모두 서로 참조하는 것
  • 다중성(Multiplicity)
    • 다대일( N:1 ) : @ManyToOne
    • 일대다( 1:N ) : @OneToMany
    • 일대일( 1:1 ) : @OneToOne
    • 다대다( N:N ) : @ManyToMany
  • 연관관계 주인(owner) : 객체를 양방향 연관관계로 만들면 연관관계의 주인을 정해야 합니다.

참조를 통한 연관관계는 언제나 단방향이며, 객체 간에 연관관계를 양방향으로 만들고 싶은 경우 반대쪽에도 필드를 추가하여 참조를 보관해야 합니다. 이러한 관계는 정확히 이야기하면 양방향 관계가 아닌 서로 다른 단방향 관계 2개입니다.

단방향

객체 연관관계 vs 테이블 연관관계

  • 객체는 참조로 연관관계를 맺습니다.
    • a.b.c
  • 참조를 사용하는 객체의 연관관계는 단방향입니다.
    • A -> B (a.b)
  • 테이블은 외래키로 연관 관계를 맺습니다.
    • JOIN
  • 외래키를 사용하는 테이블의 연관관계는 양방향입니다.
    • A JOIN B, B JOIN A
  • 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 합니다.
    • A -> B(a.b)
    • B -> A(b.a)

@JoinColumn

외래키를 매핑하는 경우 사용합니다.

속성 기능 기본값
name 매핑할 외래 키 이름 필드명 + _ + 참조하는 테이블 기본키 컬럼명
referencedColumnName 외래키가 참조하는 대상 테이블 컬럼명 참조하는 테이블의 기본키 컬럼명
foreginKey(DDL) 외래키 제약조건을 직접 지정할 수 있음
테이블을 생성할 때만 사용
insertable
(거의 사용하지 않음)
Entity 저장 시 해당 Field도 저장, false로 읽기 전용 설정 가능. true
updatable
(거의 사용하지 않음)
Entity 수정 시 해당 Field도 수정, false로 읽기 전용 설정 가능. true
table
(거의 사용하지 않음)
하나의 Entity 설정에서 두 개이상 Table에 매핑할 때 사용 현재 Class가 매핑된 Table
nullable(DDL) true/false로 null 허용 여부 설정 true
unique(DDL) true/false로 Unique 제약 조건 설정
@Table.uniqueConstraints와 동일하지만 한 컬럼에만 제약조건을 걸 때 사용
columnDefinition(DDL) DB Column 정보를 직접 설정 Java Type과 설정 DB 방언으로, 적절한 Column Type 생성

@ManyToOne

다대일(N:1) 관계에서 사용합니다.

속성 기능 기본값
optional False 설정 시 연관된 Entity가 항상 있어야 함 true
fetch global fetch 전략 설정 @ManyToOne = FetchType.EAGER
@OneToMany = FetchType.LAZY
cascade 영속성 전이 기능 사용
targetEntity
(거의 사용하지 않음)
연관된 Entity의 타입 정보 설정
컬렉션을 사용해도 제네릭으로 타입 정보 알 수 있음

조회

객체 그래프 탐색(객체 연관관계를 사용한 조회)

다음과 같이 객체를 통해 연관된 Entity를 조회하는 것을 객체 그래프 탐색이라 합니다.

val member: Member = em.find(Member.class.java, "member1")
val team: Team = member.team
println(team.name)

양방향

테이블은 외래 키 한 개로 두 테이블의 연관관계 관리하지만, 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 합니다.

  • A -> B(a.b)
    • 회원 -> 팀 ( @ManyToOne )
  • B -> A(b.a)
    • 팀 -> 회원 ( @OneToMany )

Entity를 양방향 연관관계로 설정하면 객체 참조는 2개인데, 외래 키는 한 개이며, 둘 사이에 차이가 발생하게 됩니다.

두 객체 연관관계 중 하나를 정해 테이블의 외래키를 관리해야 하는데, 이것을 연관관계의 주인(Owner) 라 합니다.

그러므로, 양방향 연관관계 매핑 시 두 연관관계 중 하나를 연관관계 주인으로 정해야 합니다.

  • 연관관계 주인 : 데이터베이스 연관관계와 매핑되고, 외래키를 관리(등록, 수정, 삭제) 할 수 있음
  • 주인이 아닌 쪽 : 읽기만 가능

mappedBy 속성을 사용해 연관관계 주인을 정할 수 있습니다.

  • 주인은 mappedBy 속성을 사용하지 않음
  • 주인이 아니면, mappedBy 속성을 사용해 연관관계의 주인을 지정해야 한다.

연관관계의 주인은 어떤 기준으로 정해야할까요? 연관관계의 주인은 외래 키 관리자를 선택하는 것입니다.

  • @OneToMany (team.members)를 연관관계 주인으로 선택하면 물리적으로 전혀 다른 테이블의 외래키를 관리해야 한다.
  • @ManyToOne (member.team)를 연관관계 주인으로 선택하면, member 테이블에 있는 외래키를 관리하면 된다.

그러므로 연관관계의 주인은 테이블의 외래 키가 있는 곳으로 정해야 하며, 객체의 양방향 연관관계는 양쪽 모두 관계를 맺어주는 것이 안전합니다.

'개발' 카테고리의 다른 글

TDD (테스트 주도 개발)  (1) 2024.09.18
동기/비동기  (0) 2024.09.18
JPA 영속성 관리  (3) 2024.09.11
GIT (2)  (0) 2024.09.10
GIT (1)  (0) 2024.09.09