JPA - 내부동작방식

지환·2024년 5월 2일

JPA

목록 보기
4/5

출처 | 나무소리 https://www.youtube.com/watch?v=mj7mOMqHM68&list=PLOSNUO27qFbvzGd3yWbHISxHctPRKkctO&index=6

JPA 내부동작 방식

  • JPA를 통해 "객체를 영속화" 하려면, EntityManager가 필요하다. EntityManager의 인스턴스 객체는 EntityManagerFactory 객체를 통해 얻는다.
  • EntityManager는 영속성 컨텍스트(PersistenceContext)를 통해 영속 객체를 관리한다

  • 사용자는 EntityManager 인스턴스 객체의 다양한 영속객체를 관리한다.

  • 영속적으로 저장하기 위해 사용되는 객체가 영속객체라고한다.
    • Customer 객체가 영속성 컨텍스트에 관리되어 진다.

영속성 컨텍스트[1/4] 개요

  • 영속성 컨텍스트(Persistence Context)는 고유 ID를 갖는 모든 영속 객체 인스턴스에 대한 집합이다.

  • 영속 객체에 대한 관리는 EntityManager의 메소드를 이용한다.

  • EntityManager를 통해 등록된 영속객체 혹은 저장소로 부터 가져온 영속객체의 정보는 "1차 캐시에서 " 관리한다.

  • 영속성 컨텍스트는 애플리케이션 영구 저장소 사이에 위치한다.

  • persist를 통해서 entityManager가 영속객체로 관리시켜주세요 라는 의미이다. -> 그렇게 되면 Persistence Context에서 관리한다. 이 부분을 1차캐시라고한다.(아직 Insert를 진행하지 않은 상태)
    • 1차 캐시에 등록된 상태 +디비에 아직 저장 x
  • 만약에 entityManager.find()
    • 1차 캐시에 존재한다면, DataBase까지 경유하지 않는다.
    • 디비에 저장되어 있는 데이터라면 디비를 경유한다.
public class CustomerJpaExam {

    public static void main(String[] args) {
        EntityManagerFactory  emf = Persistence.createEntityManagerFactory("customer-exam");
        /*entityManager를 얻어오기 위한 작업*/

        EntityManager em = emf.createEntityManager();
        // 하나의 엔티티 매니저를 갖게 됐음
        // 항상 트랜잭션 단위로 작업된다. (커밋 <-> 롤백) * 단위에 대해서 숙지해야한다. *

        EntityTransaction tx = em.getTransaction();

        tx.begin();
        /*
            em.persist(); 내가 넣을 객체를 persist() 파라미터 안에다 넣으면 된다.
        * */

        try{


            Customer customer = em.find(Customer.class,"ID0001"); // ID0001 은 PK값임
            em.persist(customer); // persist가 반드시 insert가 아니다. commit이 되어야 insert처리가 진행된다.
            em.persist(customer); // 이 때도 insert가 발생하지 않는다. 정확히 insert 되는 시점은 tx.commit()에서 진행된다. << 이 때는 1차 캐시에 저장된 상태

            tx.commit(); // 위에 persist를 2번해서 insert를 2번 하는게 아니라, commit(트랜잭션) 기준으로 진행한다.
        }
        catch (Exception e)
        {
            e.printStackTrace();
            tx.rollback();
        }finally {
            em.close();
            emf.close();
        }


    }
}

1차 캐시에서 select 하는 경우

public class CustomerJpaExam {

    public static void main(String[] args) {
        EntityManagerFactory  emf = Persistence.createEntityManagerFactory("customer-exam");
        /*entityManager를 얻어오기 위한 작업*/

        EntityManager em = emf.createEntityManager();
        // 하나의 엔티티 매니저를 갖게 됐음
        // 항상 트랜잭션 단위로 작업된다. (커밋 <-> 롤백) * 단위에 대해서 숙지해야한다. *

        EntityTransaction tx = em.getTransaction();

        tx.begin();
        /*
            em.persist(); 내가 넣을 객체를 persist() 파라미터 안에다 넣으면 된다.
        * */

        try{


            Customer customer = new Customer("ID0001", "Kim"); // ID0001 은 PK값임
            em.persist(customer); // persist가 반드시 insert가 아니다. commit이 되어야 insert처리가 진행된다.
            //em.persist(customer); // 이 때도 insert가 발생하지 않는다. 정확히 insert 되는 시점은 tx.commit()에서 진행된다. << 이 때는 1차 캐시에 저장된 상태

            Customer cus01 = em.find(Customer.class, "ID0001");
            System.out.println(cus01.toString());

            tx.commit(); // 위에 persist를 2번해서 insert를 2번 하는게 아니라, commit(트랜잭션) 기준으로 진행한다.
        }
        catch (Exception e)
        {
            e.printStackTrace();
            tx.rollback();
        }finally {
            em.close();
            emf.close();
        }


    }
}

  • Insert 하기 전에 1차캐시 부분이 나왔다.

  • Insert는 commit 됐을 때 날라간다.

  • find()를 했는데, select 쿼리를 날린게 아니라, 영속성 컨텍스트 1차캐시 커스터머 객체로 가져온거임

Customer cus01 = em.find(Customer.class, "ID0002"); 라면 select 처리된다.

profile
아는만큼보인다.

0개의 댓글