study/Project 🐾

[JPA] 즉시 로딩 / 지연 로딩

서나쓰 2021. 12. 17. 14:11
728x90

JPA를 프로젝트를 통해 야매로 배우고 나서 자신감있게 코드를 요리조리 조립해서 프로젝트를 진행했는데, 여태 에러 없이 디버깅을 진행하면서 했지만 난생 처음 보는 에러를 마주했다

LazyInitializationException

Lazy Loading으로 인한 에러인데, 구글링을 하면 굉장히 여러 이유로 에러가 나고, 해결 방법도 생각보다 여러 방법이 있다.

총 3가지의 해결 방법이 있는데 그 중, 내가 해결한 방법을 작성해본다.

 

지연 로딩 (Lazy Loading)


@Entity
public class Member {
	@id @GeneratedValue
    private Long id;
    
    
	@OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "item")
    private Team team;
}

지연 로딩은 엔티티 조회 시점이 아닌 엔티티 내 연관관계를 참조할 때 해당 연관관게에 대한 SQL이 질의되는 기능이며, LAZY 옵션으로 지정할 수 있다.

엔티티 조회시, 연관관계 필드는 프록시 객체로 제공된다.

Member.findMember = EntityManager.find(Member.class, 1L);

member.getTeam(); // 프록시 객체 초기화 X

member.getTram().getClass(); // 프록시 객체

member.getTeam().getName(); // 프록시 객체 초기화 및 SQL 질의

위 코드와 같이 지연로딩되는 연관관계를 참조하기 전까지는 프록시 객체가 초기화되지 않고, 프록시 객체를 참조할 때 객체가 초기화되고 SQL이 질의됩니다.

 

즉시 로딩


@Entity
public class Member {
	@id @GeneratedValue
    private Long id;
    
    
	@OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "item")
    private Team team;
}

즉시 로딩은 엔티티 조회 시 연관관계에 있는 데이터까지 한번에 조회해오는 기능이며, EAGER 옵션으로 지정할 수 있다.

즉시 로딩으로 조회된 엔티티의 연관관계 필드에는 실제 엔티티 객체가 반환된다.

 

주의 사항

- 실무에서는 가급적 지연 로딩만 사용

- 즉시 로딩을 사용하면 예상하지 못한 SQL이 발생할 수 있다

- 즉시 로딩은 JPQL 사용시 N+1문제를 유발한다

- 연관 관계별로 fetch 옵션 기본 값이 다르다

@ManytoOne : EAGER

@OneToOne : EAGER

@ManytoMany : LAZY

@OneToMany : LAZY

-> 즉시 로딩의 위험성을 알고 모든 연관관계를 지연 로딩으로 교체했다고 가정했을 때, 특정 비즈니스 로직에서 동시 조회를 해야하는 경우, JPQL이나 QueryDSL 의 join을 사용하면 된다

728x90