JPA 구동 방식과 영속성 컨텍스트

Ahri·2022년 5월 18일
0

HelloJPA

목록 보기
2/4

인프런 (자바 ORM 표준 JPA 프로그래밍 - 기본편, 김영한) 강의를 듣고 정리한 내용입니다

1. JPA 구동방식

1) Persistence --> 설정정보 조회 (META-INF/persistence.xml)

<persistence-unit name="hello"> //EntityManagerFactory 인자값이 됨
        <properties>
            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="유저"/>
            <property name="javax.persistence.jdbc.password" value="비밀번호"/>
            <property name="javax.persistence.jdbc.url" value="url정보"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
</persistence-unit>

2) Persistence --> EntityManagerFactory 생성(1개만)

//웹서버 올라오는 시점에 1개만 생성됨
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

emf.close();

3) EntityManagerFactory --> EntityManager 여러개 생성

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

//고객의 요청마다, 트랜잭션 단위마다 생성됨. 모든 데이터 변경은 트랜잭션 안에서 실행함
EntityManager em = emf.createEntityManager();
//code 들이 들어감
em.close();

emf.close();

2. 영속성 컨텍스트

1) 엔티티의 생명주기

  • 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
//Member 객체만 만들었음
Member member = new Member();
member.setId(1L);
member.setName("helloA");
  • 영속 (managed) : 영속성 컨텍스트에 관리되는 상태
//Member 객체를 영속성 컨텍스트에 넣음
em.persist(member);
  • 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
//영속성 분리함
em.detach(member);
//영속성 컨텍스트 완전히 초기화
em.clear();
//영속성 컨텍스트 종료
em.close()
  • 삭제 (removed) : 삭제된 상태
//찾아서 
Member findMember = em.find(Member.class, 1L);
//삭제함
em.remove(findMember);

2) 플러시(Flush) : 쿼리 바로 날려주는 기능

-> 영속성 컨텍스트에 넣었다고 해서 바로 쿼리가 실행되지 않고 커밋 직전에 실행됨

Member member = new Member();
member.setId(2L);
member.setName("hello2");

System.out.println("=========== BEFORE =========");
em.persist(member);
System.out.println("=========== AFTER =========");
=========== BEFORE =========
=========== AFTER =========
Hibernate: 
    /* insert helloJpa.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)

-> flush를 사용하면 영속성 컨텍스트의 변경내용을 바로 DB에 반영함

System.out.println("=========== BEFORE =========");
em.persist(member);
em.flush();
System.out.println("=========== AFTER =========")
=========== BEFORE =========
Hibernate: 
    /* insert helloJpa.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)
=========== AFTER =========
  • flush() 말고도 커밋시, JPQL 쿼리 실행시 플러시가 자동 호출됨

3) 영속성 컨텍스트의 이점

  • 1차 캐시 : 영속성 컨텍스트에 있는 값은 DB를 조회하지 않고 바로 가져옴
System.out.println("=========== BEFORE =========");
em.persist(member); //영속화
Member findMember = em.find(Member.class, 3L); //영속성 컨텍스트에서 가져옴
System.out.println("이름 : "+findMember.getName());
System.out.println("=========== AFTER =========");
=========== BEFORE =========
이름 : hello3
=========== AFTER =========
Hibernate: 
    /* insert helloJpa.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)
  • 동일성 보장
Member findMember1 = em.find(Member.class, 4L);
Member findMember2 = em.find(Member.class, 4L);
System.out.println(findMember1 == findMember2); //true
  • 트랜잭션 지원하는 쓰기 지연(flush, 커밋, JPQL쿼리 실행전까지 모은 영속성 컨텍스트의 SQL 실행)
  • 변경 감지 -> 엔티티와 스냅샷을 비교해서 변경이 되면 update 쿼리 생성
Member findMember1 = em.find(Member.class, 4L);
findMember1.setName("hello~~!!!!");
        update
            Member 
        set
            name=? 
        where
            id=?

0개의 댓글