JPA - 영속성 컨텍스트

JWbase·2024년 1월 8일
0

JPA

목록 보기
1/3
post-thumbnail

(해당 게시물은 JAVA ORM 표준 JPA 프로그래밍 을 듣고 정리한 글 입니다.)

JPA에서 가장 중요한 두가지!

  • 영속성 컨텍스트
  • 객체와 관계형 데이터 베이스 매핑하기(Object Relational Mapping)

영속성 컨텍스트

  • JPA를 이애하는데 가장 중요한 용어로 '엔티티를 영구 저장하는 환경'이라는 뜻이다.
  • EntityManager.persist(entity); entity를 영속성 컨텍스트에 저장한다는 의미이다.
  • EntityManager와 PersistenceContext가 매핑됨.

엔티티의 생명주기

  • 비영속(new / transient)

    • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

      
      Member member = new Member();
      member.setId("1L");
      member.setName("JWbase");
      
      객체를 생성한 상태여서 영속성 컨텍스트에서 관리 되지 않는 비영속 상태라고 부른다.
  • 영속 (managed)

    • 영속성 컨텍스트에 관리되는 상태

      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      
      // 객체를 저장한 상태 (영속)
      em.persist(member);
    • tracnsaction.commit()를 해야지만 DB에 query가 동작한다.

  • 준영속 (detached)

    • 영속성 컨텍스트에 저장되었다가 분리된 상태
      // 회원 엔티티를 영속성 컨텍스트에서 분리, 준 영속 상태
      em.detach(member);
  • 삭제 (removed)

    • 삭제된 상태
      em.remove(member);

영속성 컨텍스트의 이점

  • 1차 캐시
  • 동일성(identity) 보장
  • 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
  • 변경 감지(Dirty Checking)
  • 지연 로딩(Lazy Loading)

엔티티 조회, 1차캐시

Member member = new Member();
member.setId("1L");
member.setName("JWbase");

//1차 캐시에 저장됨
em.persist(member);

//1차 캐시에서 조회
Member findMember = em.find(Member.class, "1L");
  • 만약 Member.findMember2 = em.find(Member.class, "2L") 처럼 1차 캐시에 없는 객체를 영속성 컨텍스트에서 조회하면 DB에서 조회해서 조회해온 결과를 1차캐시에 저장하고 객체를 반환해준다.
  • 보통 영속성 컨텍스트(엔티티 매니저)는 DB트랙잭션을 만들때 만들고 닫을 때 같이 날아가기 때문에 큰 장점은 없다.

동일성(Identity) 보장

            Member findMember1 = em.find(Member.class, 120L);
            Member findMember2 = em.find(Member.class, 120L);
            System.out.println("result = " + (findMember1 == findMember2)); //true
  • 1차 캐시로 반복 가능한 읽기(Repeatable read) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 어플리케이션 차원에서 제공한다.

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

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();
        
        em.persist(memberA);
        em.persist(memberB);
        //이 코드까지 실행되더라도 INSERT문을 날리지 않는다.
        
        //commit를 하는 순간에 INSERT문을 날린다.
        transacion.commit();

변경 감지

Member member = em.find(Member.class, 160L);
member.setName("JWClassic"); //em.persist(member)를 하지 않아도 update가 된다.
  • JPA는 commit시점에 flush()를 호출하고 엔티티와 스냅샷을 비교한다.
  • 변경 된 점이 있다면 쓰기 지연 SQL 저장소에 UPDATE SQL을 생성하고 DB에 UPDATE SQL을 날린 후 커밋한다.

엔티티 삭제

Member memberA = em.find(Member.class, "memberA");

em.remove(memberA); //엔티티 삭제
profile
기억 저장소!!

0개의 댓글