8장. 프록시 - 지연로딩

| ⚡ 지연로딩

  • 실무에서 모든 연관관계는 지연로딩을 사용해라.
  • 실무에서 즉시 로딩을 사용하지 마라.
  • JPQL fetch 조인이나, 엔티티 그래프 기능을 사용해라

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Item {
    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;

}
@Entity
public class Member extends BaseEntity {

    @Id
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    
}

 

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 member = new Member();
            member.setUsername("kuser");
            member.setTeam(team);

            em.persist(member);


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

            Member m = em.find(Member.class, member.getId());

            // 해당 시점에는 프록시 객체이다.
            System.out.println("m = " + m.getTeam().getClass());
            //m = class hellojpa.Team$HibernateProxy$bqLHLVBG
            System.out.println("=-=============");


            // 사용하는 시점에 DB에서 조회한한다.
            System.out.println(m.getTeam().getName());

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }

        emf.close();
    }
}

지연로딩은 처음 MEMBER를 조회할 때 TEAM은 프록시 객체이며, 실제 TEAM객체를 불러올 때 DB에서 조회한다.

 

| ⚡ 즉시로딩 (EAGER)


  • 조회하는 시점에 조인하여 같이 조회한다.
  • MEMBER를 조회할 때 TEAM도 같이 조인하여 조회한다.
  • 실무에서는 즉시로딩을 쓰면 안된다.
  • 즉시로딩을 적용하면 예상하지 못한 SQL이 발생한다.
  • 즉시로딩은 JPQL에서 N+1 문제를 일으킨다.
  • @ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 설정
  • @OneToMany, @ManyToNamy는 기본이 지연 로딩이다.
@Entity
public class Member extends BaseEntity {

    @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;


}

 

결과

select
        member0_.MEMBER_ID as MEMBER_I1_2_0_,
        member0_.createdBy as createdB2_2_0_,
        member0_.createdDate as createdD3_2_0_,
        member0_.lastModifiedBy as lastModi4_2_0_,
        member0_.lastModifiedDate as lastModi5_2_0_,
        member0_.TEAM_ID as TEAM_ID7_2_0_,
        member0_.USERNAME as USERNAME6_2_0_,
        team1_.TEAM_ID as TEAM_ID1_3_1_,
        team1_.createdBy as createdB2_3_1_,
        team1_.createdDate as createdD3_3_1_,
        team1_.lastModifiedBy as lastModi4_3_1_,
        team1_.lastModifiedDate as lastModi5_3_1_,
        team1_.name as name6_3_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.TEAM_ID 
    where
        member0_.MEMBER_ID=?

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

8장. 프록시  (0) 2023.08.28
다대일 단반향 - 다대일 양방향  (0) 2023.08.27
[Spring JPA #7] 7장. 고급매핑  (0) 2023.08.26
[정리] 준영속  (0) 2022.03.17
[정리] 플러시 (flush())  (0) 2022.03.16

댓글

Designed by JB FACTORY