-
지연로딩, 즉시로딩JPA 2021. 8. 22. 21:56
Team과 Member의 관계가 1:N이고
member를 조회 할 때 member만 사용하는대 Team까지 가져오면 비용적 손해다.
그럴 경우 LAZY로딩을 이용해 proxy로 조회하는 방법을 쓰면된다.
ex) @ManyToOne(fetch = FetchType.LAZY) // 지연로딩
주의사항
1.기본은 모두 LAZY로딩으로 잡아 놓고, 필요한 부분만 EAGER로딩으로 변경하는 것을 권장하고 있다.
이유
1-1 JPQL로 작성시 N+1 이슈발생.
1-2 다른 팀원이 member만 조회하려고 findById를 날렸는대, team 쿼리까지나가면 당황.
2. 연관관계 별로 fetch 기본값이 다름.
@ManyToOne -> EAGER
@OneToOne -> EAGER
@ManyToMany -> LAZY
@OneToMany -> LAZY
@Entity @Setter @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @ToString(of = {"id", "name"}) public class Team { @Id @GeneratedValue @Column(name = "team_id") private long id; private String name ; @OneToMany(mappedBy = "team") List<Member> members = new ArrayList<>(); public Team(String name) { this.name = name; } }
package study.datajap.entity; import lombok.*; import javax.persistence.*; @Entity @Setter @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @ToString(of = {"id", "username", "age"}) public class Member extends BaseEntity{ @Id @GeneratedValue private long id; private String username; private int age; @ManyToOne(fetch = FetchType.LAZY) // 지연로딩 @JoinColumn(name = "team_id") private Team team; public Member(String username) { this.username = username; } public Member(String username, int age, Team team) { this.username = username; this.age = age; if(team != null){ changeTeam(team); } } public Member(String username, int age) { this.username = username; this.age = age; } public void changeTeam(Team team){ this.team = team ; team.getMembers().add(this); } }
@Test public void 지연로딩 () { Optional<Member> byId = memberRepository.findById(2L); // fetch = FetchType.EAGER OR LAZY // byId.get().getTeam() // 호출 시점에 Team 쿼리 날림 }
Hibernate: select member0_.id as id1_1_, member0_.reg_date as reg_date2_1_, member0_.update_date as update_d3_1_, member0_.reg_user_id as reg_user4_1_, member0_.update_user_id as update_u5_1_, member0_.age as age6_1_, member0_.team_id as team_id8_1_, member0_.username as username7_1_ from member member0_ where member0_.username=?
즉시로딩으로 변경할 경우 join된 쿼리가 날라가게 된다.
@ManyToOne(fetch = FetchType.EAGER) // 즉시로딩 @JoinColumn(name = "team_id") private Team team; public Member(String username) { this.username = username; }
Hibernate: select member0_.id as id1_1_0_, member0_.reg_date as reg_date2_1_0_, member0_.update_date as update_d3_1_0_, member0_.reg_user_id as reg_user4_1_0_, member0_.update_user_id as update_u5_1_0_, member0_.age as age6_1_0_, member0_.team_id as team_id8_1_0_, member0_.username as username7_1_0_, team1_.team_id as team_id1_2_1_, team1_.name as name2_2_1_ from member member0_ left outer join team team1_ on member0_.team_id=team1_.team_id where member0_.id=?
그러면 모든 연관관계를 LAZY로딩으로 바꾸었다가, 특정한 곳에서 member,team을 동시에 조회 하는 경우가 생긴다면???
-> JPQL의 패치 조인을 사용하거나 , @Entitygraph를 사용하면 된다!
'JPA' 카테고리의 다른 글
[QueryDSL] 데이터 존재 유무 체크로직 성능 테스트 (0) 2021.03.25