본문 바로가기
프로그래밍/Back-end

JPA 지연로딩 즉시로딩

by @GodWin 2024. 10. 17.

-

 

-

안녕하세요? 오늘은 JPA에서 중요한 핵심 기능인 즉시로딩과 지연로딩에 대해서 알아보도록 하겠습니다.

※ 지난 시간에서 다뤘던 프록시의 개념을 참고해주세요.

https://logger-debug.tistory.com/entry/JPA-%EC%A7%80%EC%97%B0%EB%A1%9C%EB%94%A9-%EC%A6%89%EC%8B%9C%EB%A1%9C%EB%94%A9-%ED%94%84%EB%A1%9D%EC%8B%9C-proxy

 

JPA 지연로딩 즉시로딩 프록시 proxy

- -안녕하세요? 오늘은, JPA의 연관관계 관리 중, 프록시( proxy )에 대해서 알아보도록 하겠습니다.  프록시란?: JPA에서는 불필요한 쿼리를 최적화하기 위해서는, 지연로딩과 프록시라는 개념으

logger-debug.tistory.com

 

 

지연로딩 (LAZY)

 

: 불필요한 데이터의 정보 조회를 막기 위해 사용

ex) entityA 엔티티와 entityB 엔티티가 존재하고, 서로 단방향 N:1 매핑이 되어있다는 전제하에, entityB 의 데이터를 제외 한, entityA 의 데이터만 다루고 싶을때

 

 

EntityA 엔티티 생성)

@Entity
public class EntityA {
  
  @Id @GeneratedValue
  @Column(name = "ENTITYA_ID")
  private Long id;
  
  @Column(name = "ENTITYA_NAME")
  private String name;
  
  @ManyToOne(fetch = FetchType.LAZY) // ★★★
  @JoinColumn(name = "ENTITYB_ID")
  private EntityB entityB;
  
  ...
  
}

 

EntityB 엔티티 생성)

@Entity
public class EntityB {
  
  @Id @GeneretedValue
  @Column(name = "ENTITYB_ID")
  privatae Long id;
  
  @Column(name = "ENTITYB_NAME")
  privaate String name;
  
  ...
  
}

 

샘플코드)

EntityManagerFactory emf = Persistence.createEntityManagerFactory("유닛명");
EntityManager em = emf.createEntityManager();

EntityTransaction tx = em.getTransaction();
tx.begin();

EntityB entityB = new EntityB();
entityB.setName("entityB_1");
em.persist(entityB);

EntityA entityA = new EntityA();
entityA.setName("entityA_1");
em.persist(entityA);

em.flush();
em.close();

EntityA findEntityA = em.finid(EntityA.class, entityA.getId());

// 프록시 상태 반환
System.out.println("entityA : " + entityA.getEntityB().getClass());

// 해당 시점에 실제 DB 데이터를 조회 후, 반환
System.out.println("entityA : " + entityA.getEntityB().getName());

tx.commit();

 

+

해당 내용을 설명하자면, EntityA 엔티티를 조회 할 때, EntityB 의 엔티티 정보는, 지연로딩을 사용해서 프록시로 조회를 하게 된 상태로써, EntityB 의 속성을 사용할 때, DB에서 EntityB 의 정보를 조회하게 된다.

(LAZY 로딩 == 지연로딩)

 

 

 

즉시로딩 (EAGER)

 

: 조회를 할 때, 애초부터 Join을 걸어서, 한방에 모든 데이터를 가지고 오게 된다.

: 프록시가 아닌, 실제 엔티티가 반환

: 예상치 못한 SQL 이 반환

: JQPL에서 N+1 문제 발생

 

 

EntityA 엔티티 생성)

@Entity
public class EntityA {
  
  @Id @GeneratedValue
  @Column(name = "ENTITYA_ID")
  private Long id;
  
  @Column(name = "ENTITYA_NAME")
  private String name;
  
  @ManyToOne(fetch = FetchType.EAGER) // ★★★
  @JoinColumn(name = "ENTITYB_ID")
  private EntityB entityB;
  
  ...
  
}

 

EntityB 엔티티 생성)

@Entity
public class EntityB {
  
  @Id @GeneretedValue
  @Column(name = "ENTITYB_ID")
  privatae Long id;
  
  @Column(name = "ENTITYB_NAME")
  privaate String name;
  
  ...
  
}

 

샘플코드)

EntityManagerFactory emf = Persistence.createEntityManagerFactory("유닛명");
EntityManager em = emf.createEntityManager();

EntityTransaction tx = em.getTransaction();
tx.begin();

EntityB entityB = new EntityB();
entityB.setName("entityB_1");
em.persist(entityB);

EntityA entityA = new EntityA();
entityA.setName("entityA_1");
em.persist(entityA);

em.flush();
em.close();

EntityA findEntityA = em.finid(EntityA.class, entityA.getId());

// 해당 시점에 실제 DB 데이터를 조회 후, 반환
System.out.println("entityA : " + entityA.getEntityB().getClass());

// 영속성 컨텍스트의 entityB 정보 반환
System.out.println("entityA : " + entityA.getEntityB().getName());

tx.commit();

 

+

해당 내용을 설명하자면, EntityA 엔티티를 조회 할 때, EntityB 의 엔티티 정보는, 즉시로딩을 사용해서 조회를 하게 된 상태로써, 처음부터 EntityB 의 정보를 같이 Join해서 EntityA 정보를 가지고 오게 된다.

 

 

 

연관관계들의 기본 로딩 설정 값 ★★★

 

연관관계 기본 설정값
@ManyToOne 즉시로딩
@OneToOne 즉시로딩
@OneToMany 지연로딩
@ManyToMany 지연로딩

 

 

 

오늘은 JPA에서 중요한 핵심 기능인 즉시로딩과 지연로딩에 대해서 알아보았습니다.

그럼 오늘도 즐거운 하루 되시길 바라겠습니다.