첫 번째 상황
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 |
---|