양방향 연관관계와 연관관계의 주인2 - 주의점, 정리
JPA 기준으로 보면 주인 쪽에서만 데이터 수정해주면 되지만 실제 코드에서는 양쪽 다 수정을 해주는 것이 좋다.
⭐️지연로딩 : Member.setTeam(team); 으로 주인 쪽에서만 데이터 넣어줘도 JPA에 의해서 Team의 getMembers로 리스트 조회하면 이 리스트에도 데이터가 들어가있다!
문제점
영속성 컨텍스트 1차캐시에 있던 값이 없는 team 객체를 가져온다.
member.setTeam(team);//1.주인이 왜래키 등록 em.persist(member); //team.getMembers().add(member);//2.가짜 주인도 등록해줘야함! Team findnTeam = em.find(Team.class,team.getId()); List<Member> members = findTeam.getMembers();
테스트케이스 작성시에도 JPA 없이 하기 때문에 주인 쪽에만 데이터를 넣으면 데이터 불일치성이 발생한다!
양방향 관계는 양쪽 다 값을 셋팅해줘야한다!
실제로 1번과 2번을 함께 유지해줘야하는데 떨어져있으면 깜빡하기 쉽다! =>연관관계 편의 메서드를 생성하자! 주인 쪽에서 FK를 수정하는 setter 부분에 가짜 주인의 해당 필드를 수정하는 것을 추가한다! =>원자적으로 하나만 수정해도 둘 다 동시에 수정할 수 있다! =>연관관계 편의 메서드나 JPA 상태를 변경할 때, 로직이 들어갈 때는 단순 setter를 사용하지 않고 의미에 맞게 메서드이름을 변경해준다!!! 그러면 단순히 값을 셋팅하는 것이 아니라 뭔가 의미있는 동작을 한다는 것을 명시적으로 알 수 있다!
=>Member를 기준으로 수정할지, Team을 기준으로 수정할지 둘 중 하나만 선택할 수 있다. =>1 에 할지 다 에 할지는 상황마다 다르다.
Member 클래스 기준으로 수정 : setTeam이 아니라 changeTeam으로 이름 바꾸고, team도 현재의 member로 변경
public void changeTeam(Team team) {
this.team = team;//팀을 셋팅하고
team.getMembers().add(this);//현재 회원을 팀 members에도 추가!
}
2. Team 클래스 기준으로 수정 : team.addMember(member1);
public void addMember(Member member){
member.changeTeam(this);
members.add(member);
}
양방향 매핑 시 무한 루프 조심하자!=>연관 관계 편의 메서드를 양쪽 다 실행함으로써 나오는 문제인가?
lombok의 toString() 사용❌
절대 컨트롤러가 엔티티를 직접 반환❌
이유
toString은 현재 클래스의 모든 필드들을 String으로 출력한다. Member = id, username, Team : Team의 toString 호출 Team = id, name, List<Member> : Member 컬렉션의 Member 하나하나 모두 toString 호출하고, 각 Member 내부의 toString은 다시 Team.toString()을 호출 결국 양쪽 번갈아 무한 호출&실행하는 순환참조가 일어나 스택오버플로우가 발생!
컨트롤러에서 엔티티를 response로 직접 보낼 때 엔티티가 가진 양방향 관계일 때 엔티티를 JSON으로 바꾸는 순간 발생 컨트롤러에서 엔티티반환할 때 스프링에서 엔티티를 JSON으로 뽑는다. JSON으로 API 반환해버리면 무한루프 발생 가능, 엔티티는 변경가능한데 엔티티가 변경되면 그 API 스펙이 바뀌어버린다! 그러면 API 받는 입장에서 API 변경되면 황당. 그래서 엔티티는 값만 있는 "DTO" 로 만들어서 전송한다!
em.flush() : 영속성 컨텍스트를 비우지 않고, 영속성 컨텍스트의 변경내용을 DB에 동기화 em.clear(): 영속성 컨텍스트 초기화! em.flush() + em.clear() : 영속성 컨텍스트(1차 캐시)에 아무것도 없기 때문에 DB에 다시 조회해야함! =>영속성 컨텍스트를 DB에 반영하고, 영속성 컨텍스트를 초기화하면 JPA는 DB에서 데이터를 조회하게 되고, 내부 매커니즘(지연 로딩)으로 Team의 members 리스트에도 데이터가 들어가있다! (FK값이 변경됐다는 것을 알고 members를 조회한다)
Last updated
Was this helpful?