(6) 양방향 연관관계 주의점
Last update: a year ago by nowwaterReading time: 2 min
양방향 연관관계 설정 후 가장 흔히 하는 실수는 연관관계의 주인에는 값을 입력하지 않고 주인이 아닌 곳에서 값을 입력하는 것이다.
데이터베이스에 외래 키 값이 정상적으로 저장되지 않으면 이것부터 의심해보자
양방향 연관관계 주의점
public void testSaveNonOwner() {//회원1 저장Member member1 = new Member("member1", "회원1");em.persist(member1);//회원2 저장Member member2 = new Member("member2", "회원2");em.persist(member2);Team team1 = new Team("team1", "팀1");//주인이 아닌 곳에 연관관계 설정team1.getMembers().add(member1);team2.getMembers().add(member2);em.persist(team1);}
회원을 조회한 결과
MEMBER_ID | USERNAME | TEAM_ID |
---|---|---|
member1 | 회원1 | null |
member2 | 회원2 | null |
5.6.1 순수한 객체까지 고려한 양방향 연관관계
사실 객체 관점에서 양쪽 방향에 모두 값을 입력해주는 것이 가장 안전하다.
양쪽 방향 모두 값을 입력하지 않으면 JPA를 사용하지 않는 순수한 객체 상태에서 심각한 문제가 발생할 수 있다.
JPA로 코드 완성
public void testORM_양방향() {//팀1 저장Team team1 = new Team("team1", "팀1");em.persist(team1);Member member1 = new Member("member1", "회원1");// 양방향 연관관계 설정member1.setTeam(team1); // 연관관계 설정 member1 -> team1team1.getMembers().add(member1); // 연관관계 설정 team1 -> member1em.persist(member1);Member member2 = new Member("member2", "회원2");// 양방향 연관관계 설정member2.setTeam(team1); // 연관관계 설정 member2 -> team1team1.getMembers().add(member2); // 연관관계 설정 team1 -> member2em.persist(member2);
Member.team
: 연관관계의 주인, 이 값으로 외래 키를 관리한다.
Team.members
: 연관관계의 주인이 아니다. 따라서 저장 시에 사용되지 않는다.
결론: 객체의 양방향 연관관계는 양쪽 모두 관계를 맺어주자.
5.6.2 연관관계 편의 메소드
양방향 연관관계는 결국 양쪽 다 신경 써야 한다.
member1.setTeam(team1); // 연관관계 설정 member1 -> team1team1.getMembers().add(member1); // 연관관계 설정 team1 -> member1
이렇게 각각 호출하다 보면 실수로 둘 중 하나만 호출해서 양방향이 깨질 수 있다.
두 코드를 하나인 것처럼 사용하는 것이 안전한다.
=> 연관관계 편의 메소드
: 한 번에 양방향 관계를 설정하는 메소드
public class Member {private Team team;public void setTeam(Team team) {this.team = team;team.getMembers().add(this);}}
5.6.3 연관관계 편의 메소드 작성 시 주의사항
연관관계를 변경 시 기존의 정보를 삭제하는 코드를 추가해줘야 한다.
따라서 다음 코드가 올바른 코드이다.
public class Member {private Team team;public void setTeam(Team team) {// 기존 팀과 관계를 제거if(this.team != null){this.team.getMembers().remove(this);}this.team = team;team.getMembers().add(this);}}