✏️ JPA 연관 관계 (1)

박상민·2023년 9월 30일
0

JPA

목록 보기
9/24
post-thumbnail

JPA에서 가장 중요한 것
JPA에서 가장 중요한 것은 '객체와 관계형 데이터베이스(RDB) 테이블이 어떻게 매핑되는지를 이해하는 것'이라고 생각한다.
JPA의 목적인 '객체 지향 프로그래밍과 데이터베이스 사이의 패러다임 불일치 해결'을 생각하면 이유를 알 수 있다.

⭐️ 연관관계 정의 규칙

연관관계를 매핑할 때, 3가지를 생각해야한다.

  • 방향: 단방향, 양방향(객체 참조)
  • 연관 관계의 주인: 양방향일 때, 연관관계에서 관리 주체
  • 다중성: 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:N)

📌 단방향, 양방향

데이터베이스 테이블은 외래키(FK) 하나로 양 쪽 테이블 조인이 가능하다. 따라서 데이터베이스는 단방향, 양방향을 나눌 필요가 없다.

그러나 객체는 참조용 필드가 있는 객체만 다른 객체를 참조하는 것이 가능하다. 그렇기 때문에 두 객체 사이에 하나의 객체만 참조용 필드를 갖고 참조하면 단방향 관계, 두 객체가 각각 참조용 필드를 갖고 참조하면 양방향 관계이다.

사실 양방관 관계란 없다.
두 객체가 단방향 참조를 각각 가진( <- -> ) 단방향 참조 2개를 양방향 관계라고 말하는 것이다.

JPA를 사용해서 데이터베이스와 패러다임을 맞추기 위해서 객체는 단방향 연관 관계를 가질지, 양방향 연관 관계를 가질지 선택해야한다.

선택은 비즈니스 로직에서 두 객체가 참조가 필요한지 여부를 생각하면 된다.

  • Member.getTeam()처럼 참조가 필요하면 Member -> Team 단방향 참조
  • Team.getMembers()처럼 참조가 필요하면 Team -> Member 단방향 참조

비즈니스 로직에 맞게 선택했는데 두 객체가 서로 단방향 참조를 했다면 양방향 연관 관계가 되는 것이다.

정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐
  • 단방향 매핑을 하고, 양방향은 필요할 때 추가하면 됨

✔︎ 그냥 양방향 연관 관계를 사용하면 되는거 아니야?

아니다. 객체 입장에서 양방향 연관 관계는 좋지 않다.

예를 들어 일반적인 비즈니스 애플리케이션에서 회원(Member)엔티티는 굉장히 많은 엔티티와 연관 관계를 갖는다.
이런 경우에 모든 엔티티를 양방향 관계로 설정하게 되면 회원 엔티티는 많은 테이블과 연관 관계를 맺게 되고 Member 클래스를 보면 엄청나게 복잡해진 것을 확인할 수 있다.
그리고 다른 엔티티들도 불필요한 연관관계 매핑으로 인해 복잡성이 증가할 수 있다.

좋은 기준
기본적으로 단방향 매핑으로 설계를 해야한다.
그리고 나중에 역방향으로 객체 탐색이 필요하다고 느낄 때 양방향으로 추가하면 된다.

📌 연관 관계의 주인

두 객체(A, B)가 양방향 관계를 맺을 때, 연관 관계의 주인을 지정해야 한다.

연관 관계의 주인을 지정 하는 것은 두 단방향 관계(A→B, B→A)중, 제어의 권한을 갖는 실질적인 주인이 어떤 것인지 DB의 관점으로 JPA에게 알려주는 것이다.

  • 연관 관계 주인: 두 객체 사이에서 조회, 저장, 수정, 삭제 가능

    • 외래 키(FK)가 있는 곳을 연관 관계의 주인으로 정하면 된다. 하나의 규칙인데 N:1의 관계가 있다면 N이 외래 키(FK)를 가진다.
  • 연관 관계 주인 X: 조회만 가능

    • mappedBy 속성을 사용해서 주인을 지정해줘야한다.

예시 - Member:Team = N:1

@Entity
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long Id;
    private String name;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")//Fk, 외래키
    private Team team; //연관관계의 주인
-----------------------------------------------------------
@Entity
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    
    private String name;
    
    @OneToMany(mappedBy = "team") //연관관계의 주인 지정
    private List<Member> members = new ArrayList<>();

왜 연관 관계의 주인을 지정할까?
두 객체 Member, Team이 있고 양방향 연관 관계를 갖는다 생각해보자.

이 상황에서 Member를 다른 Team으로 수정하려고 할 때, member.setTeam()으로 수정하는게 맞는지, team.setMembers()를 이용해서 수정하는게 맞는지 헷갈릴 수 있다.
두 객체의 입장에서는 두 방법 모두 맞는 방법이다.

하지만 객체에서 양방향 연관 관계를 관리하는 포인트가 각각 1개씩 있을 때는 테이블과 매핑을 담당하는 JPA 입장에서 혼란만 주게 된다.

즉, Member에서 Team을 수정할 때 FK를 수정할 지, Team에서 Member를 수정할 때 FK를 수정할지 결정하기 어려운 것이다.

그렇기 때문에 두 객체 사이의 연관 관계의 주인을 정해서 명확하게 'Member에서 Team을 수정할 때만 FK를 수정하겠다'라고 연관 관계의 주인을 지정하는 것이다.

연관 관계의 주인만 제어하면 될까?
데이터베이스에 외래 키가 있는 테이블을 수정하려면 연관 관계의 주인만 변경하는 것이 맞을까? 맞다.
하지만 이건 DB의 경우만 생각한 것이고, 객체지향적으로 생각해서 순수 객체 상태를 고려하면 하면 양쪽 다 수정하는 것이 좋다.
두 참조를 사용하는 순수한 두 객체는 데이터 동기화를 해야하기 때문이다.

✏️ JPA 연관 관계 (2)에서 다중성에 대해서 작성하겠습니다.


출처
자바 ORM 표준 JPA 프로그래밍 강의
게시글 속 자료는 모두 위 강의 속 자료를 사용했습니다.
https://jeong-pro.tistory.com/231

profile
스프링 백엔드를 공부중인 대학생입니다!

0개의 댓글