JPA의 연관관계 문제점
JPA의 영속성 컨텍스트는 데이터베이스를 객체 관점으로 관리하기 위해 만들어졌지만,
태생적인 차이로 문제점이 생기곤 하는데, 이번에는 연관관계 설정시 주의할 점을 알아보자
[데이터베이스 관점]
[객체 관점]
JPA를 사용하게되면 객체와 DB의 연관관계 방식의 불일치로 문제점이 생기게 된다.
// ----------테스트 코드 ------------//
Team team1 = new Team();
Team team2 = new Team();
team1.setName("team1");
team2.setName("team2");
teamRepository.save(team1);
teamRepository.save(team2);
Member member1 = new Member();
Member member2 = new Member();
member1.setName("AAA");
member1.setTeam(team1);
member2.setName("BBB");
member2.setTeam(team2);
memberRepository.save(member1);
memberRepository.save(member2);
위와같은 코드가 실행되었을 때, team1에는 member1이 team2에는 member2가 존재하는 상황이다.
그런데 이때, member1이 team2로 이적했다고 가정해보자.
//----------------테스트 코드----------//
member1.setTeam(team2); //member1의 team을 변경
team2.getMembers().add(member1); // team2에 member1추가
// 변경감지로 영속성 컨텍스트에 해당내용 적용됨
// 이렇게만 하면 끝일까????
분명 영속성 컨텍스트는 변경된 내용을 적용하게 된다. DB에도 원하는대로 해당 컬럼이 변경된다.
하지만 JPA의 영속성 컨텍스트와 DB는 동일한 방식으로 구성된게 아니고 객체의 특성상 문제가 발생하게 된다.
위 코드에서는 객체 team1에는 아무런 작업을 해주지 않는다. 즉, DB는 옳게 적용 되었다고 하더라도 영속성 컨텍스트의 team1에는 아직 member1이 존재하는 상태가 된다.
이 문제를 해결하기위해 둘중 주인 객체가 되는 Member의 SetTeam메소드를 다음과 같이 변경해주어야 한다.
// MemberRepository 클래스
public void setTeam(Team team){
if(this.team != null){ // 현재 멤버가 원래 팀이 있었다면 그 팀에서 삭제
this.team.getMembers().remove(this);
}
this.team = team;// 현재멤버의 팀 설정
this.team.getMembers().add(this); // 해당팀에도 멤버로 추가
}
setTeam의 메소드 자체에 멤버객체의 팀 설정, 팀 객체에 멤버추가, 이전 팀에서 삭제하는 로직을 모두 작성해줌으로써
//----------------테스트 코드----------//
member1.setTeam(team2); //member1의 team을 변경
앞서 작성한 팀 변경코드는 이렇게 변경된다.
728x90
'[IT] > JPA' 카테고리의 다른 글
[JPA] JPA 임베디드 타입 (값 타입 과 불변객체) (1) | 2021.03.25 |
---|---|
[JPA] JPA 프록시 (0) | 2021.03.22 |
[JPA] JPA의 영속성 관리 (JPA 영속성 컨텍스트) (0) | 2021.03.16 |