양방향 연관관계를 설정하고 가장 흔히 하는 실수는
연관관계의 주인에는 값을 입력하지 않고, 주인이 아닌 곳에만 값을 입력하는 것이다.
데이터베이스에 외래키 값이 정상적으로 저장되지 않으면 이것부터 의심하자.
public void testSaveNotOwner(){ //회원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); team1.getMembers().add(member2); em.persist(team1);}
회원1, 회원2를 저장하고 팀의 컬렉션에 담은 후에 팀을 저장했다.
|MEMBER_ID|USERNAME|TEAM_ID| |–|–|–| |member1|회원1|null| |member2|회원2|null|
외래키 TEAM_ID에 null 값이 들어간 이유는 연관관계의 주인이 아닌 Team.members에만 값을 저장했기 때문이다.
연관관계의 주인만이 외래키의 값을 변경할 수 있다.
사실은 객체 관점에서 양쪽 방향에 모두 값을 입력해주는 것이 가장 안전하다.
양쪽 방향 모두 값을 입력하지 않으면 JPA를 사용하지 않는 순수한 객체 상태에서 심각한 문제가 발생할 수 있다.
예를 들어 JPA를 사용하지 않고 엔티티에 대한 테스트 코드를 작성한다고 가정하자.
ORM은 객체와 관계형 데이터베이스 둘 다 중요하기 때문에 데이터베이스뿐만 아니라 객체도 함께 고려해야 한다.
//JPA를 사용하지 않는 순수한 객체//팀1Team team1 = new Team("team1", "팀1");Member member1 = new Member("member1", "회원1");Member member2 = new Member("member2", "회원2");member1.setTeam(team1); //연관관계 설정 member1 -> team1member2.setTeam(team1); //연관관계 설정 member2 -> team1List<Member> members = team1.getMembers();//member.size = 0System.out.println("members.size = " + member.size());
Member.team에만 연관관계를 설정하고 반대 방향을 연관관계를 설정하지 않았다.(0이 나온 이유)
객체까지 고려해 양방향은 양쪽 다 관계를 설정해야 한다.