[JPA] 자바 ORM 표준 JPA 프로그래밍 ch.5

박지운·2023년 7월 30일
0

김영한님의 '자바 ORM 표준 JPA 프로그래밍'을 읽고 정리한 글입니다.


5장

✔ 단방향 연관관계

회원과 팀의 관계를 통해 이해해야한다

  • 객체 기준
    회원 객체는 Member.team으로 연관을 맺는다.
    단방향이므로 team-> member는 얻을 수 없다.
  • 테이블 기준
    회원 테이블과 팀 테이블은 TEAM_ID로 연관관계를 맺는다. 조인을 할 수 있으므로 양방향 관계이다.

ManyToOne

JPA를 사용하여 위 둘을 매핑해보자.

@Entity
public class Member {
	...
    @ManyToOne
    @JoinColumn(name="TEAM_ID")
    private Team team;

여기서 @JoinColumn은 외래 키를 매핑할 때 사용한다. 생략이 가능하다.
만약 생략시 기본 전략을 이용한다.

필드명 + _ + 참조하는 테이블의 컬럼명

@ManyToOne 속성

  • optional : 기본 값 true, false시 연관 엔티티가 항상 있어야한다.
  • fetch : 글로벌 페치 전략 뒤에 나옴 (8장)
  • cascade : 영속성 전이 기능을 사용 (8장)
  • targetEntity : 연관된 엔티티 타입 정보 설정, 거의 사용 X

✔ 양방향 연관관계

반대로 팀에서 회원으로 접근하는 관계를 추가하자.

  • 회원 -> 팀(Member.team)
  • 팀 -> 회원(Team.members)

Team 엔티티

@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();

✔ 연관관계의 주인

mappedBy 속성은 왜 필요할까?

객체에는 양방향 연관관계라는 것이 없다.
서로 다른 단방향 연관간계를 묶은 것이다.

테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다.
엔티티를 단방향으로 매핑하면 참조를 하나만 사용한다.
하지만 양방향 매핑이면 객체의 참조 인데 외래 키하나 이다.

-> JPA에서는 두 연관관계 중 하나를 정해 테이블의 외래키를 관리한다. 이를 연관관계의 주인이라고 한다.

규칙

연관관계의 주인만이 외래 키를 관리(등록,수정,삭제)할 수 있다.
주인이 아닌 쪽은 읽기만 가능하다.

  • 주인은 mappedBy 속성을 사용하지 않는다.

  • 주인이아니면 mappedBy속성을 사용해 주인을 지정해야한다.

    연관관계의 주인을 정하는 것은 외래키 관리자를 정하는 것이다.
    만약 Member.team을 주인으로 선택하면 자기 테이블에 있는 외래 키를 관리하면 된다.
    하지만 Team.member를 선택하면 물리적으로 다른 테이블의 외래 키를 관리해야한다.

    연관관계의 주인은 외래 키가 있는 곳

    여기서는 회원 테이블이 외래 키를 갖고 있으므로 Member.team이 주인이 된다.
    Team.members에는 (mappedBy="team")속성을 사용해야한다. 여기서team은 Member엔티티의 team 필드이다.

    	데이터 베이스의 다대일, 일대다 관계는 항상 `다`쪽이 외래 키를 가진다.  따라서 
    	`다`쪽인 @ManyToOne은 항상 연관관계의 주인이므로 mappedBy를 설정할 수 없다.

✔ 양방향 연관관계 저장

저장 방식은 단방향 방식과 동일하다.
엔티티 매니저는 주인을 통해서 외래 키를 관리한다.

team1.getMembers().add(member1) // 무시된다.(연관관계의 주인이 아니기에!!)

team이 아닌 member 엔티티를 통해서 해야한다.

member1.setTeam(team1) //연관관계 설정

✔ 양방향 연관관계의 주의점

흔히 하는 실수는 연관관계의 주인에는 값을 입력하지 않고 주인이 아닌 곳에만 값을 입력하는 것이다.

//회원 1,2 를 저장 후
Team team1 = new Team("team1", "팀1");
//주인이 아닌 곳에만 연관관계 설정
team1.getMembers().add(member1);
team2.getMembers().add(member2);

em.persist(team1);

위에서 봤듯이 Member.team에는 null들어가게 된다.

순수한 객체까지 고려한 양방향 연관관계

그럼 주인에만 저장해도 될까? -> 객체 관점으로는 양쪽 방향 모두 값을 넣어주는 것이 안전하다.
JPA를 사용하지 않은 순수한 객체 코드에서는 null이 들어간다.
결론은 양방향 연관관계는 양쪽 모두 관계를 맺어주어야한다.


✔ 정리

  • 양방향의 장점은 반대 방향으로 객체 그래프 탐색 기능이 추가된 것.
  • 연관관계의 주인은 외래 키의 위치와 관련해서 정해야한다.(중요도로 접근 X)
  • 양방향 매핑 시 무한루프에 빠지지 않게 조심하자.
profile
앞길막막 전과생

1개의 댓글

comment-user-thumbnail
2023년 7월 30일

좋은 글이네요. 공유해주셔서 감사합니다.

답글 달기