Persistence Context

참새·2023년 5월 10일
0

영속성 컨텍스트

  • 영속성 컨텍스트는 엔티티를 영구 저장하는 환경이라는 뜻.
  • 영속성 컨텍스트는 애플리케이션과 DB 사이에서 객체를 보관하는 가상의 DB 역할.
  • 엔티티 매니저(EntityManager)를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리.

엔티티 생명주기

  • 비영속(new/transient) 상태 : 영속성 컨텍스트와 관계가 없는 상태
    //객체를 생성한 상태(비영속)
    Member member = new Member();
    member.setId("member1");
    member.setUsername("회원1");
  • 영속(managed) 상태 : 영속성 컨텍스트에 저장된 상태
    //객체를 생성한 상태(비영속)
    Member member = new Member();
    member.setId("member1");
    member.setUsername(“회원1);
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    //객체를 저장한 상태(영속)
    em.persist(member);
  • 준영속(detached) 상태 : 영속성 컨텍스트에 저장되었다가 분리된 상태
    //회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
    em.detach(member);
  • 삭제(removed) 상태 : 삭제된 상태
    //객체를 삭제한 상태(삭제)
    em.remove(member);

영속성 컨텍스트의 이점

  • 1차 캐시
    영속성 내부에는 1차 캐시가 존재. 영속 상태의 엔티티를 이곳에 저장하기 때문에 만약 엔티티를 조회했을 때 1차 캐시에 엔티티가 존재한다면 DB를 찾아보지 않아도 됨. 말 그대로 캐시로써의 기능과 장점을 가지고 있음.

  • 영속 엔티티의 동일성 보장

    Member a = em.find(Member.class, "member1");
    Member b = em.find(Member.class, "member1");
    
    System.out.println(a==b) // true

    1차 캐시로 반복 가능한 읽기(Repeatable Read) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공 가능.

  • 트랜잭션을 지원하는 쓰기 지연

    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    //엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
    transaction.begin(); // [트랜잭션] 시작
    
    em.persist(memberA);
    em.persist(memberB);
    //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
    
    //커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
    transaction.commit(); // [트랜잭션] 커밋

    em.persist()로 객체를 영속성 컨텍스트에 저장해도 DB에 바로 Insert 쿼리를 날리지 않음. SQL 쿼리들을 모아놓았다가 flush 될 때(영속성 컨텍스트의 변경내용을 DB에 반영할 때) 모아둔 쿼리를 모두 날림. 이를 쓰기 지연이라고 함.

  • 변경 감지(Dirty Checking)

    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin(); // [트랜잭션] 시작
    
    // 영속 엔티티 조회
    Member memberA = em.find(Member.class, "memberA");
    
    // 영속 엔티티 데이터 수정
    memberA.setUsername("hi");
    memberA.setAge(10);
    
    //em.update(member) 이런 코드가 있어야 하지 않을까?
    
    transaction.commit(); // [트랜잭션] 커밋

    영속성 컨텍스트에서 엔티티를 조회해서 해당 엔티티를 수정한다고 가정할 때, 조회한 엔티티를 다시 업데이트하는 코드가 있어야 할 것 같지만, 그러한 코드가 없어도 영속성 컨텍스트내의 스냅샷과 엔티티를 비교해 변경된 엔티티가 있으면 Update 쿼리를 자동으로 생성. 물론 이 Update 쿼리도 쓰기 지연이 될 수 있음.

  • 지연 로딩(Lazy Loading)
    지연로딩은 연관 관계 매핑되어 있는 엔티티를 조회 시 우선 프록시 객체를 반환하고, 실제로 필요할 때 쿼리를 날려 가져오는 기능. 즉, 필요할 때 데이터를 가져오는 기능.

profile
응애 나 아기 개발자

0개의 댓글