-
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 같은 다른 키 생성 전략을 사용해야 함