코드 그라데이션

지연 로딩 본문

Spring/JPA 공부

지연 로딩

완벽한 장면 2023. 8. 24. 12:35

반복된 고민

 

예시

Member

- Team을 살짝 변경

 

JpaMain

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

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

    try {
      //팀도 세팅
      Team team = new Team();
      team.setName("teamA");
      em.persist(team);
      
      Member member1 = new Member();
      member1.setUsername("member1");
      member1.setTeam(team);
      em.persist(member1);

      em.flush();
      em.clear();

      Member m = em.find(Member.class, member1.getId());
      System.out.println("m = " + m.getTeam().getClass());

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      e.printStackTrace(); // 하나 찍어봄
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

멤버를 조회할 때는 멤버만 가져오고, 팀은 프록시로 가져오는 것을 확인할 수 있음.

Hibernate: 
    select
        member0_.MEMBER_ID as member_i1_3_0_,
        member0_.createdBy as createdb2_3_0_,
        member0_.createdDate as createdd3_3_0_,
        member0_.lastModifiedBy as lastmodi4_3_0_,
        member0_.lastModifiedDate as lastmodi5_3_0_,
        member0_.TEAM_ID as team_id7_3_0_,
        member0_.USERNAME as username6_3_0_ 
    from
        Member member0_ 
    where
        member0_.MEMBER_ID=?
11:19:03.102 [main] DEBUG org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl - On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.jpaExample.Member#2]
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `createdBy` : value = null
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`createdBy`)  - enhanced for lazy-loading? - false
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `createdDate` : value = null
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`createdDate`)  - enhanced for lazy-loading? - false
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `lastModifiedBy` : value = null
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`lastModifiedBy`)  - enhanced for lazy-loading? - false
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `lastModifiedDate` : value = null
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`lastModifiedDate`)  - enhanced for lazy-loading? - false
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `memberProducts` : value = NOT NULL COLLECTION
11:19:03.106 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`memberProducts`)  - enhanced for lazy-loading? - false
11:19:03.107 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `team` : value = 1
11:19:03.107 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`team`)  - enhanced for lazy-loading? - false
11:19:03.110 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `username` : value = member1
11:19:03.110 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`username`)  - enhanced for lazy-loading? - false
11:19:03.110 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.jpaExample.Member#2]
11:19:03.111 [main] DEBUG org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader - Done entity load : inflearn.exjpa.jpaExample.Member#2
m = class inflearn.exjpa.jpaExample.Team$HibernateProxy$3y6UBNCz

 

 

쿼리는

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

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

    try {
      //팀도 세팅
      Team team = new Team();
      team.setName("teamA");
      em.persist(team);
      
      Member member1 = new Member();
      member1.setUsername("member1");
      member1.setTeam(team);
      em.persist(member1);

      em.flush();
      em.clear();

      Member m = em.find(Member.class, member1.getId());
      System.out.println("m = " + m.getTeam().getClass());
      
      System.out.println("이전===================");
      m.getTeam().getName(); // 쿼리 나가는 시점
      System.out.println("이후===================");

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      e.printStackTrace(); // 하나 찍어봄
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

로그는

// 팀을 터치하는 시점에 멤버를 먼저 조회
11:21:37.063 [main] DEBUG org.hibernate.SQL - 
Hibernate: 
    select
        member0_.MEMBER_ID as member_i1_3_0_,
        member0_.createdBy as createdb2_3_0_,
        member0_.createdDate as createdd3_3_0_,
        member0_.lastModifiedBy as lastmodi4_3_0_,
        member0_.lastModifiedDate as lastmodi5_3_0_,
        member0_.TEAM_ID as team_id7_3_0_,
        member0_.USERNAME as username6_3_0_ 
    from
        Member member0_ 
    where
        member0_.MEMBER_ID=?

m = class inflearn.exjpa.jpaExample.Team$HibernateProxy$4I9ogux7 // 클래스 타입(프록시) 찍고
이전===================
11:21:37.077 [main] DEBUG org.hibernate.internal.SessionImpl - Initializing proxy: [inflearn.exjpa.jpaExample.Team#1]
11:21:37.077 [main] DEBUG org.hibernate.SQL - 

// 실제 팀을 사용하는 시점에 프록시 객체가 초기화되면서 DB에서 이 값을 가지고 온다.
Hibernate: 
    select
        team0_.TEAM_ID as team_id1_7_0_,
        team0_.createdBy as createdb2_7_0_,
        team0_.createdDate as createdd3_7_0_,
        team0_.lastModifiedBy as lastmodi4_7_0_,
        team0_.lastModifiedDate as lastmodi5_7_0_,
        team0_.name as name6_7_0_ 
    from
        Team team0_ 
    where
        team0_.TEAM_ID=?
11:21:37.078 [main] DEBUG org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl - On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.jpaExample.Team#1]
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `createdBy` : value = null
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`createdBy`)  - enhanced for lazy-loading? - false
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `createdDate` : value = null
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`createdDate`)  - enhanced for lazy-loading? - false
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `lastModifiedBy` : value = null
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`lastModifiedBy`)  - enhanced for lazy-loading? - false
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `lastModifiedDate` : value = null
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`lastModifiedDate`)  - enhanced for lazy-loading? - false
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `members` : value = NOT NULL COLLECTION
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`members`)  - enhanced for lazy-loading? - false
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `name` : value = teamA
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`name`)  - enhanced for lazy-loading? - false
11:21:37.079 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.jpaExample.Team#1]
11:21:37.079 [main] DEBUG org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader - Done entity load : inflearn.exjpa.jpaExample.Team#1
이후===================

 

지연 로딩으로 세팅하면

연관된 걸 프록시로 가지고 온다.

 

지연 로딩

 

 

지연 로딩 LAZY를 사용하여 프록시로 조회

 

 

728x90

'Spring > JPA 공부' 카테고리의 다른 글

지연 로딩 활용  (0) 2023.08.24
즉시 로딩  (0) 2023.08.24
프록시  (0) 2023.08.24
실전 예제 - 4. 상속관계 매핑  (0) 2023.08.23
@MappedSuperclass  (0) 2023.08.23
Comments