[JPA] 더티 체킹
Jpa Update할 때 변경되는 값만 수정되게 하고 싶습니다라는 질문을 보고 정리한 더티 체킹 ~
더티체킹이란
더티 체킹이 무엇인지 알아보자
아래 코드를 확인해 보자
@Service
public class UserService {
...
public void updateUser(Long id, String name) {
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction txt = em.getTransaction();
tx.begin(); // 트랜잭션 시작
User user = em.find(User.class, id);
user.changeName(name); // 엔티티만 변경
tx.commit(); // 트랜잭션 커밋
}
...
}
코드를 보면 별도로 데이터 베이스에 save 하지 않는다.
- 트랜잭션 시작
- 엔티티 조회
- 엔티티의 값 변경
- 트랜젝션 커밋 보는것과 같이 데이터 베이스에 update 쿼리를 보내지 않는다.
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
UserRepository userRepository;
@Autowired
UserService userService;
@After
public void tearDown() throws Exception {
userRepository.deleteAll();
}
@Test
public void 엔티티매니저로_확인() {
//given
User user = userRepository.save(new User(1l, "한승우"));
//when
String updateName = "test2";
userService.updateNName(user.getId, updateName);
//then
User saved = userRepository.findAll().get(0);
assertThat(saved.getName()).isEqualTo(updateName);
}
}
위 테스트 코드를 실행하면 어떤 결과를 보여줄까? save 메소드로 변경사항을 저장하지 않아도 UPDATE 쿼리가 실행된다.
이것을 Dirty Checking 이라고한다.
여기서 Dirty란 상태의 변화가 생긴 정도로 이해하면 된다. 즉, Dirty Checking 이란 상태 변경 검사를 말한다.
JPA 에서는 트랜잭션이 끝나는 시점 에 변화가 있는 모든 엔티티 객체를 데이터 베이스에 자동으로 반영해준다.
이떄 변화가 있다면 기준은 최초 조회 상태이다.
JPA 에선 엔티티를 조회 하면 해당 __엔티티의 조회 상태 그대로 스냅샷__을 만들어 놓는다.
그리고 트랜잭션이 끝나는 시점에 이 스냅샷과 비교하여 다른 점이 있다면 Update Query 를 데이터베이스에 전달한다. (check 검사의 대상은 영속성 컨텍스트가 관리하는 엔티티에만 적용이 된다.)
- detach 된 엔티티 (준영속)
- DB에 반영되기전 처음 생성된 엔티티 (비영속) 등 준영속/비영속 상태의 엔티티는 Dirty Checking의 대상ㅇ이 아니다. 즉 값을 아무리 변경해도 데이터베이스에 반영이 되지 안흔ㄴ다.
변경 부분만 update 하기
Dirty Checking으로 생성되는 update 쿼리는 기본적으로 __모든 필드__를 업데이트 한다. JPA 에서는 전체 필드를 업데이트 하는 방식을 기본으로 한다.
전체 필드 업데이트의 장점
- 생성되는 쿼리가 같아 부트 실행시점에 미리 만들어 재사용 가능
- 데이터베이스 입장에서 쿼리 재사용이 가능해진다.
- 동일한 쿼리를 받으면 이전에 파싱된 쿼리를 재사용한다.
@DynamicUpdate
@DynamicUpdate를 통해 변경된 필드만 반영 되도록 하는것이 가능하다.
엔티티 최상단에 아래와 같이 @DynaicUpdate 를 선언해준다.
@Entity
@DynamicUdpate // 변경한 필드만 대응
public class User {
...
@Id
@GenerateValue(strategy = GenerationType.IDENTITY)
private Long id;
...
}
참고
https://www.baeldung.com/spring-data-jpa-dynamicupdate https://jojoldu.tistory.com/415