JPA에서 Flush(), tx.commit() 의 차이점

HyunJunSon·2024년 5월 1일
0

문제상황을 통해 배운점

 EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
           //변경감지

            Member member1 = new Member(1L, "son");
            Member member2 = new Member(2L, "choi");
            Member member3 = new Member(3L, "kim");

            em.persist(member1);
            em.persist(member2);
            em.persist(member3);
            em.flush();


            Member member = em.find(Member.class, 3L);
            member.setName("changedName");
            System.out.println("===========B");
            Thread.sleep(2000);
            member.setId(11L);
//
            System.out.println("===========C");

            tx.commit();

        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
            emf.close();
        }
  • JPA의 변경감지를 테스트 해보려다, 위와같은 코드를 작성했다.
  • 3명의 사람을 영속화시킨후, flush를 했다.
  • 1차 캐시에 쌓이던 데이터가 flush로 동기화 되었으니, 1차캐시를 비었고, tx(트랙젝션)도 끝났다고 생각해서, 아래줄에서 tx.begin()을 다시 해주었더니 에러가 발생했다.

flush는 단순 데이터 동기화만 되고, 트랙젝션을 끝내지는 않는다.

flush를 한다고 해서 1차캐시의 데이터가 초기화 되지는 않는다. clear()를 통해 초기화할수는 있다.

  • 변경감지는 값을 set 하는 순간이 아니라, commit 하는 순간에 쿼리를 날린다.
  • JPQL 쿼리를 실행하면 플러시가 자동 호출된다.

(출처 : 김영한 JPA자 바 ORM 표준 JPA 프로그래밍 - 기본편)

  • 이유는 위와 같이 쓰기지연저장소에 쌓여 있는 데이터가 1차캐시에 있는 상태로는 JPQL 쿼리를 실행할수가 없기 때문에 JPQL은 실행전에 flush()를 실행한후, 실행된다.
profile
즐겁게 공부하고 사람들에게 도움을 주는 개발자가 되고 싶습니다.

0개의 댓글