728x90
반응형
양방향 연관관계의 주의점
- 값 조회 안되는 경우
- 무한루프에 빠지는 경우
값조회가 안되는 경우
예제설명
양방향 연관관계를 쓸때는 양쪽에 값을 다 넣어 줘야 된다.
앞서예제에서 Member 에도 team이 있고 Team 에도 Members 가 있었다.
여기서 Member에만 team을 넣어 주고 Team에다가 Member를 넣어주지 않으며 어떻게 될까?
예제로 살펴보자.
예제1 Member 에만 Team을 넣어 주었을때
- 1. Team을 생성한다.
- 2. Team을 영속성 컨텍스트에 넣는다.
- 3. 새로운 회원을 만든다.
- 4. 회원을 영속성 컨텍스트에 넣는다.
- 5. 주석처리...
- 6. flush 를 이용하여 DB에 저장한다.
- 7. 영속성컨텍스트에 있는 모든 정보를 날린다.
- 8. 영속성컨텍스트가 비어있기 때문에 DB에서 가져온다.
- 9. Team 에서 members를 가져온다
- 10. 영속성컨텍스트에 내용이 없기 때문에 조회 할때 DB 에서 조회한다.
- 여기 까지는 문제가 없다 문제는 다음예제에서 설명한다.
1. Team team = new Team();
team.setName("TeamA");
2. em.persist(team);
// 수정코드
3. Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
4. em.persist(member);
// Member에만 setTeam으로 팀을 넣어주었다.
//5. team.getMembers().add(member);
// select 쿼리를 보고 싶을때
6. em.flush(); // 영속성에있는 데이터를 DB 에 저장
7. em.clear(); // 영속성 컨텍스트 모두 클리어
// 조회시 수정코드
// 쿼리문 한번 발생
8. Member findMember = em.find(Member.class, member.getId());
9. List<Member> members = findMember.getTeam().getMembers();
10. for(Member m : members)
{
// 조회시 쿼리문 발생한다.
System.out.println("m: " + m.getUsername());
}
그림으로 설명
예제2 Member 에만 Team을 넣어 주었을때 flush 와 clear를 안해주었을때.
- 1. Team을 생성한다.
- 2. Team을 영속성 컨텍스트에 넣는다.
- 3. 새로운 회원을 만든다.
- 4. 회원을 영속성 컨텍스트에 넣는다.
- 5. 주석처리
- 6. 주석처리
- 7. 주석처리
- 8. 영속성컨텍스트가 비어있기 때문에 DB에서 가져온다.
- 9. Team 에서 members를 가져온다
- 10. 영속성컨텍스트에 내용이 없기 때문에 조회 할때 DB 에서 조회한다.
조회 실패!!!!!!!!
이유는 다음과 같다.
- 단순히 여기서는 영속성컨텍스트에만 데이터들이 있다.
- 그렇기 때문에 실제로 Team 클래스의 Members 컬렉션에는 Member가 들어가 있지 않다.
1. Team team = new Team();
team.setName("TeamA");
2. em.persist(team);
// 수정코드
3. Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
4. em.persist(member);
// Member에만 setTeam으로 팀을 넣어주었다.
//5. team.getMembers().add(member);
// select 쿼리를 보고 싶을때
//6. em.flush(); // 영속성에있는 데이터를 DB 에 저장
//7. em.clear(); // 영속성 컨텍스트 모두 클리어
// 조회시 수정코드
// 쿼리문 한번 발생
8. Member findMember = em.find(Member.class, member.getId());
9. List<Member> members = findMember.getTeam().getMembers();
10. for(Member m : members)
{
// 조회시 쿼리문 발생한다.
System.out.println("m: " + m.getUsername());
}
그림으로 설명
당연 멤버에 team을 저장만 했고
team 에는 Member를 저장하지 않았기 때문에 값을 찾아오지 못한다.
예제3 Member 와 Team 양방향에는 둘다 값을 넣어주자!!
- 1. Team을 생성한다.
- 2. Team을 영속성 컨텍스트에 넣는다.
- 3. 새로운 회원을 만든다.
- 4. 회원을 영속성 컨텍스트에 넣는다.
- 5. Team 의 Members 에도 member를 넣어준다.
- 6. flush 를 이용하여 DB에 저장한다.
- 7. 영속성컨텍스트에 있는 모든 정보를 날린다.
- 8. 영속성컨텍스트가 비어있기 때문에 DB에서 가져온다.
- 9. Team 에서 members를 가져온다
- 10. 영속성컨텍스트에 내용이 없기 때문에 조회 할때 DB 에서 조회한다.
1. Team team = new Team();
team.setName("TeamA");
2. em.persist(team);
// 수정코드
3. Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
4. em.persist(member);
// Team의 members 에도 값을 넣어줌
5. team.getMembers().add(member);
// select 쿼리를 보고 싶을때
6. em.flush(); // 영속성에있는 데이터를 DB 에 저장
7. em.clear(); // 영속성 컨텍스트 모두 클리어
// 조회시 수정코드
// 쿼리문 한번 발생
8. Member findMember = em.find(Member.class, member.getId());
9. List<Member> members = findMember.getTeam().getMembers();
10. for(Member m : members)
{
// 조회시 쿼리문 발생한다.
System.out.println("m: " + m.getUsername());
}
예제4 헷갈리수도 있으니 코드를 개선해보자
Member 에서 Team 저장할때 member 도 같이 저장하기
Main 코드
1. Team team = new Team();
team.setName("TeamA");
2. em.persist(team);
// 수정코드
3. Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
4. em.persist(member);
// Team의 members 에도 값을 넣어줌
//5. team.getMembers().add(member);
// select 쿼리를 보고 싶을때
6. em.flush(); // 영속성에있는 데이터를 DB 에 저장
7. em.clear(); // 영속성 컨텍스트 모두 클리어
// 조회시 수정코드
// 쿼리문 한번 발생
8. Member findMember = em.find(Member.class, member.getId());
9. List<Member> members = findMember.getTeam().getMembers();
10. for(Member m : members)
{
// 조회시 쿼리문 발생한다.
System.out.println("m: " + m.getUsername());
}
Member에서 member도 같이 넣어주기
changeTeam 메소드를 이용하여 team을 넣어주고 동시에 team에서 members 컬렉션을 불러와 넣어 주었다.
public class Member {
...
...
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
...
...
}
무한루프에 빠지는 경우
Member 에서 toString을 할경우
team을 출력시 다시 Team에 가서 toString을 수행한다.
그럼 team에서 다시 Member의 toString을 호출하면서 무한 루프에 빠진다.
Member
public class Member {
...
...
@Override
public String toString() {
return "FullDuplexMember{" +
"id=" + id +
", username='" + username + '\'' +
", team=" + team +
'}';
}
...
...
}
Team
@Entity
public class Team {
@Override
public String toString() {
return "Team{" +
"id=" + id +
", members=" + members +
", name='" + name + '\'' +
'}';
}
}
그림설명
728x90
반응형
'DataBase > JPA' 카테고리의 다른 글
[JPA] 연관관계 매핑기초4: 정리 (0) | 2021.08.03 |
---|---|
[JPA] mappedBy (0) | 2021.08.02 |
[JPA] 연관관계 매핑기초2: 양방향 연관관계 (0) | 2021.08.02 |
[JPA] 연관관계 매핑기초1: 단방향 연관관계 (0) | 2021.08.01 |
[JPA] 기본매핑 (0) | 2021.08.01 |
댓글