[ TIL ] JPA 의 변경 감지 기능

charco·2021년 10월 19일
0

나도TIL

목록 보기
50/55

JPA에서 엔티티 수정하기

JPA는 마치 컬렉션을 수정하듯이 엔티티를 수정할 수 있게 해준다.


// 트랜잭션 시작
Car car = em.find(Car.class, 1L);
car.setBrand("kia");
// 트랜잭션 종료 (커밋)

em.find() 로 조회한 car는 영속성 컨텍스트가 관리하는 엔티티다.
위의 코드를 실행하면 무슨 일이 일어날까?
뭔가 허전해보이지만,
DB에 UPDATE 쿼리가 날아간다.

/** JPQL **/
update Car c set c.brand = 'kia' where c.id = 1;

읭? 코드는 JVM 에서만 동작할 것 같이 생겼지만,
네트워크를 타고 DB까지 쿼리가 날아간다.
무슨일이 일어났던 것일까?


영속성 컨텍스트

이 신기한 마법을 부리는 장본인은 영속성 컨텍스트다.
영속성 컨텍스트는 엔티티를 보관할때 최초 상태를 복사해서 따로 저장해둔다.
이것을 스냅샷이라고 한다.
그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다.

위의 코드가 실행될 때 영속성 컨텍스트가 하는 일의 과정을 보면 이렇다.

  1. em.find() 가 호출된다. 파라미터로 받은 식별자로 1차 캐시에서 먼저 엔티티가 있는지 확인한다. 없으면 DB에서 조회한다.

  2. 조회한 엔티티 (최초 상태)를 복사해서 따로 저장해둔다.(스냅샷)

  3. car.setBrand() 메서드가 호출되면서 엔티티가 변경됐다.

  4. 커밋 전에, EntityManager 의 flush() 메서드가 호출된다.

  5. 이때 스냅샷과 현재 엔티티를 비교한다.

  6. 차이가 있으면 수정 쿼리를 생성해 쓰기 지연 SQL 저장소에 보관한다.

  7. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.

  8. 데이터베이스 트랜잭션을 커밋한다.

여기서 주의해야 할 점은 변경감지 기능은 트랜잭션 안에서만 활성화된다는 것이다.
만약 트랜잭션 밖에서 엔티티를 수정한다면 아무 일도 일어나지 않는다.

주의해서 엔티티를 수정하자!

profile
아직 배우는 중입니다

0개의 댓글