Back-End/JPA

JPA - 양방향 연관관계와 연관관계의 주인, 양방향 매핑 정리

LightSource 2022. 9. 27. 19:47

이 글은 이전글인

JPA - 연관관계 매핑(조인 방법), 단방향 연관 관계 및 매핑

과 이어집니다.

 

JPA - 연관관계 매핑(조인 방법), 단방향 연관 관계 및 매핑

JPA에서의 연관관계를 알아볼때 목표 객체지향적인 패러다임과 관계형 DB가 지향하는 패러다임의 차이를 이해해야 한다. 객체의 참조와 테이블의 외래 키를 매핑 용어 방향(Direction) : 단방향, 양

scoring.tistory.com

양방향 매핑 방법

  • Member와 Team 테이블의 연관 관계로 설명

Member.java

@Entity
public class Member {

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

    @Column(name = "USERNAME")
    private String username;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
...
}

Team.java

@Entity
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "TEAM_ID")
    private long id;
    private String name;

    @OneToMany(mappedBy = "team")  // Member객체의 team과 연관관계 매핑
    private List<Member> members = new ArrayList<>();

    public List<Member> getMembers() {
        return members;
    }
  • 양방향 매핑시 다대일(N:1)인 객체(Member)는 @ManyToOne@JoinColumn 을 이용해서 매핑했다.
  • 나머지 일대다(1:N)인 객체(Team)는 @OneToMany(mappedBy = "team") 을 이용해서 매핑했다.
  • 연관되는 서로의 객체를 멤버변수(매핑 컬럼 설정)로 등록 시켜서 매핑을 해야한다.

객체 탐색

Member findmember = em.find(Member.class, member.getId());
List<Member> members = findmember.getTeam().getMembers();

for(Member m : members) {
    System.out.println("m.getUsername() = " + m.getUsername());
}

양방향 연관관계에서 테이블과 객체의 차이

테이블 연관관계 = 1개

  • 회원 ↔팀의 연관관계 1개(양방향)
  • 테이블은 외래 키(MEMEBER.TEAM_ID) 하나로 두 테이블의 연관관계를 관리

객체 연관관계 = 2개

  • 회원 → 팀 연관관계 1개(단방향)
  • 팀 → 회원 연관관계 1개(단방향)
  • 객체의 양방향 관계는 서로 다른 단방향 관계 2개로 이루어져 있다.

객체 매핑에서 오는 딜레마

그렇다면, Member객체의 Team값을 바꿧을때, MEMBER.TEAM_ID값이 바뀌어야 하는지, Team객체의 List members 값을 바꿧을때 MEMBER.TEAM_ID값이 바뀌어야 하는지 어떻게 결정하는가?

연관관계의 주인(Owner)으로 지정해서 관리

양방향 매핑 규칙

  • 객체의 두 관계중 하나를 연관관계의 주인으로 지정
  • 연관관계의 주인만이 외래 키를 관리(등록, 수정)
  • 주인이 아닌쪽은 읽기만 가능
  • 주인은 mappedBy 속성 사용X
  • 주인이 아니면 mappedBy 속서으로 주인 지정

연관 관계의 주인(Owner) 지정 방법

  • 외래키가 있는 곳을 주인으로 지정할것!
    → Team의 객체에서 값을 바꿧는데, MEMBER테이블에 쿼리문이 나가면 혼란스럽다.
  • 예시에서는 Member.team이 연관관계의 주인

양방향 매핑시 가장 많이 하는 실수

연관관계의 주인에 값을 입력하지 않는 경우 값이 들어가지 않음

연관관계의 주인에 값을 입력한 경우, 값이 잘 들어감

  • 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정할 것
    연관관계 편의 메소드를 생성하자

연관관계 편의 메소드

Member.java  

public void setTeam(Team team) {
        this.team = team;            // 멤버에 팀을 세팅할 때

        team.getMembers().add(this); // team의 Member값에 this값을 넣어서 Member값을 세팅해준다.
    }
  • 양방향 매핑시에 무한 루프를 조심할 것!
    toString(), lombok , JSON 생성 라이브러리 사용시 양방향으로 매핑되면, 무한루프에 빠진다
    • toString 사용 x, lombok에서 toString 사용하는것 생성 x, JSON에서 엔티티 반환하는것 사용하지 말것 → dto로 변환해서 반환

양방향 매핑 정리

  • 단방향 매핑으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대 방향으로 조회 기능이 추가된 것
  • JPQL에서 역방향으로 탐색할 일이 많다.
  • 단방향 매핑을 우선하고, 양방향이 필요할 때 추가 해도 된다. (양방향 추가시 테이블을 바꾸지 않기 때문에 코드 몇줄만 추가하면 되기 때문)
  • 연관관계의 주인을 정하는 기준
    → 외래 키의 위치를 기준으로 정할 것!

참고

이글은 김영한 님의 JPA 프로그래밍 강의를 바탕으로 쓰여졌습니다

https://www.inflearn.com/course/ORM-JPA-Basic

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

반응형