저번 포스팅에서는 양방향 연관관계의 기본적인 부분에 대해서 알아보았습니다.
이번에는 양방향 연관관계를 맺을 때 주의해야 할 점에 대해서 알아보겠습니다.
모든 코드는 Github 에 올라와있습니다.
양방향 매핑 시 자주 하는 실수
mappedBy 된 변수에 값을 입력하려고 한다.
분명히 team.getMembers()를 통해서 값을 넣어줬다. 하지만 H2 DB에 가서 조회를 해보면?
Member 테이블에 TEAM_ID = null인걸 확인할 수 있다. 값이 들어가지 않은 것이다.
team.getMember.add(member)
로 값을 넣어줬지만 왜 값이 들어가지 않은 것일까?
기본적으로 mappedBy
속성이 붙은 변수는 JPA에서 조회 용도로 사용된다.
member
에 team
을 넣고 싶다면 member.setTeam(team)
을 해줘야한다.
정상적으로 Member에 TEAM_ID가 들어갔다.
JPA의 입장으로만 보면 여기까지 하면 연관관계 주인과 종속을 잘 설정하였고 값도 잘 들어갔다.
team.getMembers()
해서 값을 꺼내보면 값이 잘 출력이 된다.
insert도 두 번 정상적으로 나가고 MEBMER_ID도 출력이 된다.
하지만 문제는 DB에 값을 넣지 않은 상태이기 때문에 tx.commit()
전에 값을 조회하려고 하면 값이 나오지 않는다.
이런 문제를 해결하기 위해서 양쪽에 값을 넣어주는 것이 좋다.
결론은 양방향 연관관계 매핑에서는 양쪽에 값을 세팅해 주는 것이 좋다.
양방향 매핑을 할 때 항상 빠짐없이 양쪽에 값을 세팅해 줄 수 있다면 좋겠지만, 더 편리한 방법으로 메서드를 만들어서 사용하는 것이 좋다.
김영한 님의 강의에서는 이를 연관관계 편의 메서드하고 했다.
연관관계 편의 메소드
Member
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
}
Member
의 changeTeam()
에서 team
을 세팅하는 시점에 team.getMembers.add()
코드로 Member
와 Team
양쪽에 데이터를 넣어준다.
주의사항
양방향 매핑 시에 무한 루프를 조심하자
- toString(), lombok, JSON 생성 라이브러리
최대한 단방향 연관관계로 설계를 끝내고 양쪽으로 조회할 일이 생기면 그때 양방향으로 매핑을 해도 괜찮다.