Blog

[Spring][JPA]53 Fetch Type, 지연로딩(LAZY), 즉시로딩(EAGER)

Category
Author
Tags
PinOnMain
1 more property
다음과 같은 연관 관계를 참고하여 Entity를 작성해보자.
Member.java
@Entity public class Member { @Id @GeneratedValue @Column(name = "MEMBER_ID") private Long id; @Column(name = "USERNAME") private String username; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "TEAM_ID") private Team team; }
Java
복사
Team.java
@Entity public class Team { @Id @GeneratedValue @Column(name = "TEAM_ID") private Long id; private String name; @OneToMany(mappedBy = "team") private List<Member> members = new ArrayList<>(); }
Java
복사
Team과 Member는 양방향 연관관계이며 키의 주인은 Member이다.(@JoinColumn으로 Team타입의 team변수는 Team클래스의 mappedBy로 참조되어있다.) 또한 Team Entity에서는 @OneToMany로 List<Member>를 Member 엔티티의 team 참조변수에 맵핑하고 있다.
눈 여겨 볼 곳은 'fetch = FetchType.EAGER' 부분이다. 앞서 JPA를 설명하면서 한번도 사용하지 않은 속성인데, FetchType을 EAGER로 설정했다. (참고로 @ManyToOne 매핑의 기본 fetch가 EAGER라서 생략해도 EAGER로 동작한다.)
Team team = new Team(); team.setName("teamA"); em.persist(team); Member member = new Member(); member.setUsername("member1"); member.setTeam(team); em.persist(member); em.flush(); em.clear(); Member findMember = em.find(Member.class, member.getId());
Java
복사
Team 객체와 Member 객체를 각각 만들고 Member 객체의 Setter 메소드를 통해 Team 객체를 셋팅해준 뒤 em.find() 메소드를 통해 Member를 조회한다.
여기서 중요한 점은 분명 Member를 조회했다는 점이다. 이제 결과 로그를 살펴보자
EAGER일 때
Hibernate: select member0_.MEMBER_ID as MEMBER_I1_0_0_, member0_.TEAM_ID as TEAM_ID3_0_0_, member0_.USERNAME as USERNAME2_0_0_, team1_.TEAM_ID as TEAM_ID1_1_1_, team1_.name as name2_1_1_ from Member member0_ left outer join Team team1_ on member0_.TEAM_ID=team1_.TEAM_ID where member0_.MEMBER_ID=?
Java
복사
분명 Member를 조회했는데 왜 Team까지 join되어 쿼리가 나간걸까?
이 마법이 fetch = FetchType.EAGER 의 결과이다.
LAZY일 때
Hibernate: select member0_.MEMBER_ID as MEMBER_I1_0_0_, member0_.TEAM_ID as TEAM_ID3_0_0_, member0_.USERNAME as USERNAME2_0_0_ from Member member0_ where member0_.MEMBER_ID=?
Java
복사
이번엔 Member만 딱 조회해오는것을 볼 수 있다.
그리고 아래와 같이 Member 객체로 부터 Team 객체의 데이터를 실질적으로 요구하는 코드를 만나면 Team 데이터를 조회하는 쿼리문이 나간다.
EAGER는 사전적 의미인 열심인, 열렬한 처럼 Member를 조회하면 연관관계에 있는 Team 역시 함께 조회는 반면에, LAZY는 게을러서 Member만 조회해오고 연관관계에 있는 나머지 데이터는 조회를 미룬다.
EAGER가 필요한 경우
비지니스 로직 상 Member 데이터가 필요한 곳에 대부분 Team의 데이터 역시 같이 사용 할 필요가 있다면 어떨까? FetchType을 EAGER로 설정하여 항상 Member와 Team을 같이 조회해오는 것이 더 좋을 것
LAZY가 필요한 경우
Member를 사용하는 곳 대부분에서 Team 데이터가 필요하지 않다면? FetchType을 LAZY로 설정하여 Member만 조회하고, 드물게 Team이 필요할 땐 그 때 Team에 대한 쿼리를 한번 더 날려 조회하는것이 좋을 것이다.