Skip to main content

연관관계 매핑

·353 words·2 mins· loading
Table of Contents
JPA - This article is part of a series.
Part 4: This Article

연관관계 매핑이 필요한 이유
#

DB는 기본적으로, 연관관계의 방향이 없다. (FK로 join걸면 다 해결됨) 하지만 객체는 참조를 사용해서 관계를 맺는다. 따라서, 객체지향적인 방법으로 데이터를 조작하려면 연관관계 매핑이 필수적이다.


단방향 연관관계
#

객체의 참조FK를 매칭

@Entity
public class Member{
	@Id @GeneratedValue
    private Long id;
    ...
    
    @ManyToOne
    @JoinColumn(name = "TEEAM_ID")
    private Team team;
}

@ㄷEntity
public Class Team{
...
@OneToManty(mappedBy = "team")
private List<Member> members = new ArrayList<>(); //관례적으로 넣어줌
}

양방향 연관관계
#

연관관계의 주인이란?
#

테이블은 FK 하나로 연관관계를 관리하지만, 객체는 양쪽에 참조 객체가 있다. 따라서, 두 관계의 주인(OWNER)를 지정해줘야 한다.

  • 연관관계의 주인만이 FK를 관리하고, 다른쪽은 읽기만 가능하다.
  • 주인은 @JoinColumn으로 외래키 속성 설정
  • 주인이 아닌 쪽에서 mappedBy 를 이용해 주인을 지정한다.

그러면 어느 쪽을 주인으로 해야 할까?

FK가 있는쪽 (여기선 Member.team) 을 주인으로 정하자. 이건 단지 비즈니스상의 중요성과는 아무 관계가 업는, FK를 관리할 쪽을 정하는거임.

주인에 항상 값을 넣어줘야 함
#

// 틀린 예시
Team team = new Team();
em.persist(team);

Member member = new Member();

team.getMembers.add(member);  //역뱡향에서 값을 넘

em.persist(member) ; // member.TEAM_ID = NULL
// 올바른 예시
Team team = new Team();
em.persist(team);

Member member = new Member();

//team.getMembers.add(member);  //주인이 아닌 곳에서 값을 넘
memeber.setTeam(team) // 주인이 값을 넘
em.persist(member) ; // member.Team_id값이 들어감

주인 쪽에도 값을 넣어줘야 하는 이유
#

em.flush(), em.clear()가 호출되지 않는 상태에서, 엔티티는 1차 캐시에 있음 -> 이 상황에서는 member.team은 설정되어 있어도, team.membersNull임 -> 따라서, 이왕이면 Team에도 Member 값이 세팅되어 있어야 함

주의사항
#

@ToString, Json 생성 라이브러리 등을 사용할때, 무한루프가 돌 수 있음

///member.toString()
   @Override
   public String toString() {
   		return "Member{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", team=" + team + // team.toString() 호출
                '}';}
   @Override
   public String toString() {
   		return "Team{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", members=" + members + // (member1.toSTring,2.toString ...)
                '}';
    }
    System.out.println(team.getMember()) ==> StackOverflowError

해결법
#

  • Entity 자체를 내보내거나, 받아오지 말자 (DTO 사용)
  • @ToString 등을 사용할땐 조심하자

정리
#

  • 단방향 매핑만 해도 이미 연관관계 매핑은 끝난거임
  • 양방향이라는건, 반대 방향으로 조회하는 기능이 추가된 것 뿐임
  • 따라서, 단방향 매핑만 잘 해놓고 필요할 때 추가하면 됨
  • 편의 메서드 이용
 public void addMember(Member member) {
        member.setTeam(this);
        members.add(member);
    }
JPA - This article is part of a series.
Part 4: This Article