연관관계 매핑 - 기본

hoonie·2023년 3월 19일
0

자바 표준 ORM: JPA

목록 보기
3/3
post-thumbnail

이 포스트는 인프런 김영한님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'의 내용을 정리한 포스트 입니다.

연관관계 매핑에 대한 이해

  • 객체와 테이블의 연관관계의 차이를 이해
  • 객체의 참조와 테이블의 외래키를 매핑하는 과정
  • 용어에 대한 이해
    • 방향: 양방향, 단방향
    • 다중성: 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M)
    • 연관관계의 주인(Owner): 객체의 양방향 관계에서는 관리 주인이 필요

객체와 테이블의 연관관계 차이

  • 객체는 참조를 사용해서 연관관계를 찾는다.
  • 테이블은 외래 키로 조인을 해서 연관관계를 찾는다.
  • 객체와 테이블에는 이러한 큰 차이가 존재한다.

다대일(N:1) 단방향 연관관계

  • MemberTeam 엔티티를 N:1 단방향 연관관계 매핑을 해보자
  • Member는 하나의 Team에만 속할 수 있다.
@Entity
public class Member {
	@Id @GeneratedValue
    private Long id;
    private String name;
    
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    ...
    
}
  • Member의 입장에서는 Team@ManyToOne이다.
  • 이때 테이블의 외래 키는 "TEAM_ID"이므로 @JoinColumn에 외래키의 정보를 넘겨줘야 한다.
  • 단방향 연관관계 매핑을 하였으므로 이제 양방향 연관관계 매핑에 대해 알아보자.

다대일(N:1) 양방향 연관관계

  • MemberTeam 엔티티를 N:1 양방향 연관관계 매핑을 해보자
  • Member는 하나의 Team에만 속할 수 있고 Team은 여러 명의 Memeber를 가질 수 있다.
  • Member엔티티는 앞서 연관관계 매핑을 해주었으므로 이제 Team엔티티를 수정해보자.
@Entity
public class Team {
	@Id @GeneratedValue
    private Long id;
    
    private String name;
    
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
    
    ...
    
}
  • Team의 입장에서 Member를 여러 개 가질 수 있으므로 리스트로 선언해주고 @OneToMany어노테이션을 달아준다. 이때 연관관계에 대한 정보를 MappedBy를 활용해서 Memberteam과 연관관계에 있음을 알려준다.

연관관계의 주인과 mappedBy

객체와 테이블이 관계를 맺는 방식의 차이

  • 객체: 연관관계 -> 2개
    • 회원 -> 팀: 1개 (단방향)
    • 팀 -> 회원: 1개 (단방향)
    • 즉, 객체의 경우 양방향은 2개의 단방향 관계가 합쳐진 것이다.
  • 테이블: 연관관계 -> 1개
    • 회원 <-> 팀: 1개 (양방향)
    • 테이블의 경우엔 외래 키 하나로 두 테이블의 연관관계를 관리한다.

객체의 경우 테이블의 외래 키를 관리하는 주인을 정해줘야한다.

연관관계의 주인(Owner)

  • 양방향 매핑 규칙
    • 객체의 두 관계 중 하나를 연관관계의 주인으로 설정
    • 연관관계의 주인만이 외래 키를 관리(등록, 수정)
    • 주인이 아닌 쪽은 읽기만 가능
    • 주인은 mappedBy 속성 사용X
    • 주인이 아닌 쪽은 mappedBy 속성으로 주인을 지정
  • 그러면 누구를 주인으로 하면 좋을까?
    • 테이블에서 외래 키가 있는 곳을 주인으로 정하자!
    • 현재의 예시에서는 Member테이블이 외래 키를 갖고 있으므로 주인으로 정한다.

양방향 매핑시 연관관계의 주인에 값을 입력해야한다.

  • 오류를 방지하기 위해 두 엔티티에 모두 값을 입력해주면 좋다.
Team team = new Team();
team.setName("teamA");
em.persist(team);

Member member = new Member();
member.setName("member1");

team.getMembers().add(member);

// 연관관계의 주인에 값을 반드시 설정해줘야한다.
members.setTeam(team);

em.persist(member);

양방향 연관관계에서 주의해야할 점

  • 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자.
  • 따라서 연관관계의 주인에 값을 입력하는 과정에서 반대편에도 값이 입력될 수 있도록 하는 '연관관계 편의 메소드'를 생성해서 잠재적인 오류를 최소화하자.
  • 양방향 매핑시에 무한 루프를 조심하자.
    • toString(), lombok, JSON생성 라이브러리

정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
    • 우선 단방향 매핑으로만 연관관계들을 설정해주고 이후에 비즈니스 로직을 수행할 때 필요하다면 양방향 매핑을 설정해주자!
  • 양방향 매핑은 반대 방향으로 조회기능을 추가하는 것뿐이다!
  • JPQL에서 역방향으로 탐색할 일이 많다.
  • 연관관계의 주인을 정하는 기준
    • 연관관계의 주인은 테이블에서 외래 키를 갖고 있는 엔티티로 설정한다.
    • 비즈니스 로직을 기준으로 연관관계의 주인을 선택하면 안된다.
profile
사우루스 팡팡!

0개의 댓글