연관관계 매핑이 필요한 이유#
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.members는Null임 -> 따라서, 이왕이면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);
}