일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 김영한
- 인터셉터의 정의
- application-properties
- 쿠키의 정의
- 401오류
- .orelseThrow
- @Controller
- filter vs interceptor
- springSecurityFilterChain 오류
- Validation
- spring
- 필터의 정의
- 필터vs인터셉터
- SpringMVC
- java.lang.AssertionError
- n+1
- BindingResult
- Testcode
- MVC
- 유연한 컨트롤러1 - v5
- 구글 보안 api 활용
- controller
- spring MVC
- 세션이란
- 쿠키란
- optional
- abap value in field Data Class error
- 세션vs쿠키
- 세션의 정의
- jpa
- Today
- Total
ABAP DUMP ERROR 24시
Jpql fetch join 이 뭐야? ,N+1 예시 본문
# 인프런 김영한의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 개인적으로 정리한 글입니다.
정리
Q . fetch join이 뭐야?
실무에서 자주 사용하며, 연관된 엔티티 컬렉션을 sql문 한방으로 조회하는 쿼리다.
흔히 N+1 문제의 해결 방안으로 제시되곤 한다.
//N+1 문제란 JPA에서 query 1개를 호출했는데 DB에는 N개의 query가 호출되어 나가는 현상.
Q .fetch = fetchType.EAGER 와 fetch join과의 차이점이 뭐야?
둘다 join query가 나가는 것은 비슷하다.
하지만 EARGER는 묵시적인 특성으로. 내가 나타내지 않는 쿼리명령어 이외의 쿼리가 나가면서 join 이 이루어진다.
따라서 추적이 어렵다.
fetch join은 암시적인 특성으로, 내가 join 하고싶은 객체들을 찝어서 쿼리명령어를 작성하기 때문에 추적이 쉽다.
Q. fetch join 어떻게 사용해?
"select m from Member m join fetch m.team";
가져와 (맴버를) 어디서 (맴버로 부터) 함께 가져와 (맴버의 팀도 같이)
예시와 같이 from 뒤에 사용되며 member와 연관된 team을 가져오고 싶을때 다음과 같이 사용한다.
즉 함께 Join된 새부 내용을 가져오고싶을때 사용한다.
살펴보기
1.Member가 team의 fk 를 갖는, 즉 왜래키를 갖는 엔티티가 주인이 된다 라는 전략으로 class를 작성하였다. + 양방향 연관관계
2. 원하는 결과는 다음과 같다.
<왼쪽 3개는 Member Table 나머지 두개는 team Table + inner join 전략>
id | name | team_id | id | name |
1 | 회원A | 1 | 1 | 팀A |
2 | 회원B | 1 | 2 | 팀B |
3 | 회원C | 2 | 3 | 팀C |
@Entity
@Getter@Setter
public class Team {
@Id@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team" )
private List<Member> members = new ArrayList<>();
}
@Entity
@Getter
@Setter
public class Member{
@Id@GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
@Column(name = "NAME")
private String username;
private int age;
@Override
public String toString() {
return "Member{" +
"id=" + id +
", username='" + username + '\'' +
", age=" + age +
'}';
}
public void changeTeam(Team team){
this.team = team;
team.getMembers().add(this);
}
}
2. Test에 Member , team 변수들을 생성해준다.
Team teamA = new Team();
teamA.setName("팀A");
em.persist(teamA);
Team teamB = new Team();
teamB.setName("팀B");
em.persist(teamB);
Team teamC = new Team();
teamC.setName("팀C");
em.persist(teamC);
Member member1 = new Member();
member1.setUsername("회원1");
member1.changeTeam(teamA);
em.persist(member1);
Member member2 = new Member();
member2.setUsername("회원2");
member2.changeTeam(teamB);
em.persist(member2);
Member member3 = new Member();
member3.setUsername("회원3");
member3.changeTeam(teamC);
em.persist(member3);
Case1 ) fetch join 사용 안했을 시 = > N+1문제 발생
String query = "select m from Member m";
List<Member> members = em.createQuery(query, Member.class)
.getResultList();
for (Member member : members) {
System.out.println("members = " + member.getUsername()+
"teamName =" + member.getTeam().getName());
}
//회원1 ,팀A(SQL);// 회원 2, 팀A(1차캐시)
1번째 : member를 조회하는 query
2번째 : 회원 1에 맞는 TeamA를 가져오는 query
3번째 : 회원 2에 맞는 TeamA를 가져온다 ==> 이미 TeamA를 가져왔기때문에 1차 캐시에서 가져오므로 query안나감
4번째 : 회원 3에 맞는 TeamB를 가져오는 query
=> 총 3방의 쿼리가 나간다.
Case2 ) fetch join 사용 했을시
String query = "select m from Member m join fetch m.team";
List<Member> members = em.createQuery(query, Member.class)
.getResultList();
for (Member member : members) {
System.out.println("members = " + member.getUsername()+
"teamName =" + member.getTeam().getName());
}
member 조회할때 Team 정보까지 가져온다.
=> 총 1방의 쿼리가 나간다.
'[WEB]Back-end > JPA' 카테고리의 다른 글
Fetch join 의 한계가 뭐야? (0) | 2022.01.24 |
---|---|
@OneToMany 일 때 fetch join 시 data의 량이 늘어난다? (0) | 2022.01.22 |
JPQL이 뭐야? 어떻게 사용해? (0) | 2022.01.21 |
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 전략 (0) | 2022.01.21 |
컬렉션 값 타입 (Collection value type)의 한계 (0) | 2022.01.20 |