A와 B 테이블이 서로 연관관계 매핑이 되어있다고 해보자.
비즈니스 로직에서 단순히 A 로직만 사용하고 싶은데 B까지 함께 조회되면 손해이다.
JPA는 이 문제를 지연로딩 LAZY를 사용해서 프록시로 조회하는 방법으로 해결한다.
@ManyToOne
관계로 매핑되어 있는 상황에서 FetchType 를 설정해줄 수 있다.@Entity
@Getter
@Setter
public class A extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer number;
private String testname;
// 패치 타입 LAZY 설정
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "b_id")
private B b;
}
메인 함수에서 A만을 조회하여 aTemp 객체에 담은 뒤, aTemp 객체의 B객체에 접근하면 해당 객체는 Proxy 객체이다.
A aTemp = em.find(A.class, a.getId());
System.out.println(aTemp.getB().getClass()); // Proxy 객체 프린트 - $HibernateProxy$, B객체의 필드에 접근하지 않음 (쿼리 안나감)
LAZY 로딩에서 B 테이블에 대한 조회 쿼리는 A 객체에서 B객체의 필드에 접근하는 순간 나간다
A aTemp = em.find(A.class, a.getId());
System.out.println(aTemp.getB().getClass());// 아직 프록시 객체, 필드에 접근하지 않음
System.out.println(aTemp.getB().getNumber()); //이 때 select * from B b로 쿼리 나감
@ManyToOne
이 5개 있는데 전부 EAGER
로 설정되어 있으면 조인이 5개나 일어난다. 실무에서는 테이블 연관관계가 복잡하고 많기 떄문에 웬만하면 지연로딩을 지향한다.select a from A a
만 보면 당연히 Member만 select 하게 된다. 근데 EAGER
타입으로 설정되어 있음을 시스템상에서 뒤늦게 알게 되면 뒤늦게 B까지 SELECT 한다. 이럴거면 LAZY 로딩이 훨씬 낫다.실무에서는 LAZY 로딩 전략으로 쓴다
근데 대부분 A와 B를 함께 조회해서 쓰기 때문에 LAZY로딩이 비효율적이다 싶은 경우에는 어떻게 해야할까?
이런 경우 JPQL의 fetch join을 통해서 해당 시점에 한방 쿼리로 가져와서 쓸 수 있다.