ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA test - 2
    카테고리 없음 2024. 10. 30. 16:34

    JPA의 성능 최적화 기능

    1차 캐시와 동일성 (identity) 보장

    • 같은 트랜잭션 안에서는 같은 엔티티를 반환함
    EmployeeFindTest.java
    package jpajava;
    
    import domain.Employee;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    public class EmployeeFindTest {
      public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpatest");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
    
        tx.begin();
        System.out.println("TRANSACTION STARTED");
        try {
          System.out.println("비영속 상태");
          System.out.println("DB에서 가져옴");
          Employee emp1 = em.find(Employee.class, "202402");
          System.out.println("employee.getEmpName() : " + emp1.getEmpName());
          System.out.println("commit 전");
          tx.commit();
          System.out.println("commit 후");
          System.out.println("1차 캐시에서 가져옴");
          Employee emp2 = em.find(Employee.class, "202402");
          System.out.println("employee.getEmpName() : " + emp2.getEmpName());
    
          // 1차 캐시와 동일성(identity) 보장
          System.out.println("emp1 == emp2 : " + (emp1 == emp2));
    
        } catch (Exception e) {
          tx.rollback();
          System.out.println("TRANSACTION ROLLBACK");
          System.out.println("[Error] " + e.getMessage());
        } finally {
          System.out.println("TRANSACTION ENDED");
        }
      }
    
    }
    실행 결과

     


    트랜잭션을 지원하는 쓰기 지연 (Transactional Write Behind)

    • 트랜잭션을 commit 할 때까지 INSERT SQL을 전송하지 않고 지연시킴
    • commit하는 순간, 모아둔 INSERT SQL을 한번에 전송함 (Update, Delete도 마찬가지)
    src/main/java/jpajava/EmployeeWriteBehind.java
    package jpajava;
    
    import domain.Employee;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    public class EmployeeWriteBehind {
      public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpatest");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
    
        tx.begin();
        System.out.println("TRANSACTION STARTED");
        try {
          Employee emp1 = new Employee("202403", "아이린", null, "2024-01-01", 600);
          Employee emp2 = new Employee("202404", "슬기", null, "2024-01-01", 600);
          Employee emp3 = new Employee("202405", "조이", null, "2024-01-01", 600);
          em.persist(emp1);
          em.persist(emp2);
          em.persist(emp3);
    
          System.out.println("commit 전");
          tx.commit();
          System.out.println("commit 후");
        } catch (Exception e) {
          tx.rollback();
          System.out.println("TRANSACTION ROLLBACK");
          System.out.println("[Error] " + e.getMessage());
        } finally {
          System.out.println("TRANSACTION ENDED");
        }
      }
    }
    실행 결과 - 쓰기 지연 적용 O

     


    src/main/java/jpajava/DeptWriteBehind.java
    package jpajava;
    
    import domain.Department;
    import domain.Employee;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    public class DeptWriteBehind {
      public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpatest");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
    
        tx.begin();
        System.out.println("TRANSACTION STARTED");
        try {
          Department dept1 = new Department();
          dept1.setDeptName("AA");
          Department dept2 = new Department();
          dept2.setDeptName("BB");
          Department dept3 = new Department();
          dept3.setDeptName("CC");
    
          em.persist(dept1);
          System.out.println("dept1 생성");
          em.persist(dept2);
          System.out.println("dept2 생성");
          em.persist(dept3);
          System.out.println("dept3 생성");
    
          System.out.println("commit 전");
          tx.commit();
          System.out.println("commit 후");
        } catch (Exception e) {
          tx.rollback();
          System.out.println("TRANSACTION ROLLBACK");
          System.out.println("[Error] " + e.getMessage());
        } finally {
          System.out.println("TRANSACTION ENDED");
        }
      }
    }
    실행 결과 - 쓰기 지연 적용 X

     

     

    @GeneratedValue(strategy = GenerationType.IDENTITY)를 사용하면 쓰기 지연(write-behind)이 제대로 적용되지 않음

    • IDENTITY 전략이 데이터베이스의 AUTO INCREMENT 기능을 통해 기본 키를 즉시 할당받기 때문에, 엔티티를 persist하는 순간 즉시 INSERT 쿼리를 실행해야만 기본 키 값을 가져올 수 있기 때문!!
    • 쓰기 지연을 활용하려면 GenerationType.SEQUENCE나 GenerationType.TABLE 같은 다른 키 생성 전략을 사용해야 함
Designed by Tistory.