JPA 양방향 연관관계

2022. 12. 23. 17:11·BackEnd/자바 ORM 표준 JPA 프로그래밍

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

단방향 객체 연관관계와 테이블 연관관계는 변한 것이 없다. 그 이유는 테이블은 join으로 모든 방향으로 연관이 가능하기 때문에 방향이란 개념이 존재하지 않는다.

@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<>();
 	..Getter/Setter   
 }

저번시간에 한 Team에 List를 추가해줄 경우 양방향에서 접근을 할 수 있다. Team에서도 멤버 접근이 가능하고 멤버에서도 Team으로 접근이 가능해진다.

 

연관관계의 주인과 mappedBy

객체와 테이블간의 연관관계를 맺는 차이를 이해해야 한다.

 

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

  • 위의 예제에서 객체 연관관계는 2개이다. 회원 -> 팀 연관관계 1개(단방향), 팀 -> 회원 연관관계 1개(단방향)
  • 테이블 연관관계는 1개가 존재한다. 회원 <-> 팀의 연관관계 1개(양방향)

객체의 양방향 관계

이걸로 볼 때 객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개이다. 객체를 양방향으로 참조하려면 단방향 연관관계 2개를 만들어야 한다. 

 

테이블의 양방향 연관관계

테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다. 양쪽으로 조인 가능하다.

 

문제점

Team team을 변경할 때, Member에 있는 Team을 변경해야 할지 Team에 있는 List members를 변경해야 할지 혼란이 생긴다. 테이블의 Member는 TEAM_ID만 변경하면 되므로 테이블은 상관이 없다. 그래서 둘 중의 하나로 외래 키를 관리해야 한다. 그것이 연관관계 주인(Owner)이다.

연관관계의 주인(Owner)

양방향 매핑 규칙

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

누구를 주인으로?

외래 키가 있는 곳을 주인으로 정하자. 외래키가 있는 곳이 DB에서 N : 1로 매칭이 된다. 즉 외래키가 있는 곳이 N인 것이다. 여기서는 Member.team이 연관관계의 주인이다. 진짜 매핑 = 연관관계의 주인, 가짜 매핑 = 주인의 반대편 

Tip = 외래키가 있는 곳 즉, N인 곳을 주인으로 지정하자

 

주의할 점

Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 
 Member member = new Member();
 member.setName("member1");
 
 //역방향(주인이 아닌 방향)만 연관관계 설정
 team.getMembers().add(member);
 em.persist(member);

이렇게 할 경우 TEAM_ID는 NULL이 된다. 그 이유는 team은 가짜 매핑이기 때문에 add 할 때 고려를 하지 않는다.

Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 
 Member member = new Member();
 member.setName("member1");
 
 //연관관계의 주인에 값 설정
 member.setTeam(team); 
 em.persist(member);

이렇게 진짜 매핑 member에 값을 추가 할 경우 정상적으로 수행된다.

Team team = new Team();
team.setName("TeamA");
em.persist(team);

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

team.getMembers().add(member); 
member.setTeam(team); 
em.persist(member);
 
Member findMember = em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();

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

tx.commit;
//team.getMembers().add(member)가 없을 경우 m은 출력이 안된다.
//commit하기 전까지 영속성 컨테이너에만 메모리 상태로 들어 있기 때문이다.
//그래서 team.getMembers().add(member)를 세팅해야 commit하기전 값을 알 수 있다.
//그러므로 team과 member 모두 값을 세팅해야한다.

양방향 연관관계일 경우 양쪽 모두 값을 세팅해야한다.

이것을 헷갈리지 않게 하기 위해 연관관계 편의 메소드를 생성하자.

public void setTeam(Team team){ //changeTeam 같이 이름도 중요하게 변경
	this.team = team;
    team.getMembers().add(this);//연관관계 편의 메소드
 }

양방향 매핑 시에 무한 루프가 발생할 수 있다.

toString() 일 경우 Member에서 team을 출력, team에서 members를 출력하므로 무한 루프가 발생한다.

되도록이면 toString()과 lombock은 사용하지 않는다. JSON 생성 라이브러리는 컨트롤러에서 ENTITY를 반환하지 않는다.

 

양방향 매핑 정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료할 수 있다.
  • 양방향 매핑은 반대 뱡향으로 조회 기능이 추가된 것 뿐이다.
  • JPQL에서 역방향으로 탐색할 일이 많아진다.
  • 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 된다, 테이블에 영향을 주지 않는다.

강의 출처 : https://www.inflearn.com/course/ORM-JPA-Basic

 

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

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

www.inflearn.com

 

'BackEnd > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글

JPA 다양한 연관관계 매핑  (0) 2022.12.26
JPA 실전 예제2 - 연관관계 매핑 시작  (0) 2022.12.23
JPA 단방향 연관관계  (0) 2022.12.23
JPA 실전 예제 1 - 요구사항 분석과 기본 매핑  (0) 2022.12.23
JPA 엔티티 매핑(필드와 컬럼 매핑, 기본 키 매핑)  (1) 2022.12.22
'BackEnd/자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
  • JPA 다양한 연관관계 매핑
  • JPA 실전 예제2 - 연관관계 매핑 시작
  • JPA 단방향 연관관계
  • JPA 실전 예제 1 - 요구사항 분석과 기본 매핑
인프라 감자
인프라 감자
  • 인프라 감자
    삶은 인프라
    인프라 감자
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 클라우드&인프라 (28)
        • 인프라 공부 (4)
        • AWS 구조와 서비스 (18)
        • 클라우드 공부 (4)
        • Terraform (2)
      • AWS Cloud School (13)
        • project (5)
        • Linux, Network (6)
        • Docker (2)
      • BackEnd (162)
        • JAVA 공부 (15)
        • 알고리즘 공부 (71)
        • MySQL 문제 풀기 (8)
        • 스프링 핵심 원리 - 기본편 (18)
        • 스프링 MVC 1편 (4)
        • 자바 ORM 표준 JPA 프로그래밍 (21)
        • 실전! 스프링 부트와 JPA 활용1 (8)
        • 실전! 스프링 부트와 JPA 활용2 (5)
        • 스프링 데이터 JPA (8)
        • Querydsl (4)
      • 혼자하는 프로젝트 (32)
        • 배달의 민족 클론코딩 (7)
        • 나만의 프로젝트 (10)
        • 스프링 부트로 구현한 웹 (15)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Email
    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    스프링 핵심 원리-기본편
    VPN
    네트워크 기본 용어
    완전탐색
    자바
    이것이 자바다
    조합
    쿼드 압축
    디팬스 게임
    중첩 선언
    백트래킹
    상속
    linux
    유니온 파인드
    자동 배포
    다이나믹 프로그래밍
    정렬
    querydsl
    프로그래머스
    dp
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
인프라 감자
JPA 양방향 연관관계
상단으로

티스토리툴바