상세 컨텐츠

본문 제목

[JPA/Hibernate]엔티티 수정/ 변경감지(Dirty Checking)

JPA

by 코코코차 2024. 5. 30. 15:16

본문

728x90

엔티티를 수정하면 어떤 일이 일어날까?

 

일단 엔티티를 수정하는 코드를 보자

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();

//영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");

//영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);

transaction.commit();

 

여기서 엔티티를 Set하는 코드만 있고, Update하는 코드는 없다.

 

JPA로 엔티티를 수정할때는 단순히 엔티티를 조회해서 데이터만 변경하면 된다.

 

엔티티의 데이터만 변경했는데 어떻게 데이터베이스에 반영이 되는걸까??

 

순서대로 말해보자면 

  1. JPA는 엔티티의 영속성 컨텍스트에 보관할때 최초 상태를 복사해서 저장해둔다. 이것을 스냅샷이라고 한다.
  2. 플러시(쓰지 지연 SQL에서 데이터 베이스로 쿼리를 보내는것) 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다.
  3. 변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL저장소에 보낸다.
  4. 쓰기 지연 저장소의 SQL을 데이터베이스에 보낸다.
  5. 데이터베이스 트랜잭션을 커밋한다.

 

여기서 3번의 변경된 엔티티를 감지해서 실행된 UPDATE SQL을 보면

UPDATE MEMBER
SET
	NAME=?,
	AGE=?,
	GRADE=?,
	...
WHERE
	Id=?

 

JPA의 기본 전략에서는 이렇게 멤버의 name,age만 수정되는것이 아니라 모든 필드를 업데이트 한다. 

 

이렇게 모든 필드를 사용하면 전송량이 증가한다 하지만 왜 이렇게 했을까?

  • 모든 필드를 사용하면 수정쿼리가항상 같다. 따라서 애플리케이션 로딩 시점에 수정 쿼리를 미리 생성해두고 재사용할 수 있다.
  • 데이터베이스에 동일한 쿼리를 보내면 데이터베이스는 이전에 한 번 파싱된 쿼리를 재사용할 수 있다.

만약 필드가 많거나 저장되는 내용이 너무 크면

 

"@org.hibernate.annotation.DynamicUpdate" 어노테이션을 사용해서 수정된 데이터만 사용해서 동적으로 UPDATE SQL을 생성할 수 도 있다. 

 

여기서 참고할 것은 이런 변경감지는 영속성 컨텍스트가 관리하는 영속상태의 엔티티에만 적용이 된다. 

728x90
반응형

관련글 더보기