첫 번째 상황

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;


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("le2sky");
            member.setTeam(team);
            em.persist(member);
            
            team.getMembers().add(member);

            Member findMember = em.find(Member.class, member.getId());
            List<Member> members = findMember.getTeam().getMembers();
            for (Member m : members) {
                System.out.println("m = " + m.getUsername());
            }
            
            
            tx.commit();
        } catch (Exception err) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();

    }

}

 

위와 같은 상황에서는 1차 캐시에 team, members, member가 모두 존재해서 insert 쿼리만 두 번 나간다. 

 

 

두 번째 상황

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;


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 = em.find(Team.class, 1L);
            Member member = new Member();
            member.setUsername("le2sky");
            member.setTeam(team);
            em.persist(member);

            team.getMembers().add(member);

            Member findMember = em.find(Member.class, member.getId());
            List<Member> members = findMember.getTeam().getMembers();
            for (Member m : members) {
                System.out.println("m = " + m.getUsername());
            }
            
            
            tx.commit();
        } catch (Exception err) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();

    }

}

 

위와 같은 상황에서는 team을 1차 캐시에 올리고, team의 members를 지연 로딩한다. 따라서, insert 쿼리 1개와 team 조회 쿼리 1개, 그리고 members 조회 쿼리 1개까지 총 3개의 쿼리가 나간다.

 

 

 

세 번째 상황

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;


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 {

            Member findMember = em.find(Member.class, member.getId());
            List<Member> members = findMember.getTeam().getMembers();
            for (Member m : members) {
                System.out.println("m = " + m.getUsername());
            }
            
            
            tx.commit();
        } catch (Exception err) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();

    }

}

 

위와 같은 상황에서는 member 조회(em.find(Member.class,id))와 team 조회(getTeam)가 조인 쿼리로 대체되어 1개로 날린다. 그리고, members 조회 쿼리 1개(지연 로딩)를 날려 총 2개의 쿼리가 날아간다.

 

 

회고

위 세개의 상황 말고, 추가로 다른 상황이 떠오르면  추가해야겠다. 일단 위 3개의 상황을 잘 예측하고, 영속성 컨텍스트와 연관 지어 이야기할 수 있다면 JPA 공부에 도움이 될 것 같다.

'개발(레거시) > JPA' 카테고리의 다른 글

[JPA] N + 1 문제  (0) 2022.11.22
이하눌