@Transactional
public Long update(Long id, PostUpdateRequestDto requestDto) {
Posts posts = postRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("게시글이 존재하지 않습니다."));
posts.update(requestDto.getTitle(), requestDto.getContent());
return id;
}
위 코드는 JPA를 사용해 서비스단에 구현한 포스트의 업데이트 로직이다.
보통 JPA를 사용해 update 로직을 만들 때 데이터베이스에 쿼리를 직접 던지는 부분이 없다.
하지만 업데이트를 실행해보면 update 쿼리가 잘 작동한다.
왜???🤔
바로 JPA의 영속성 때문.
영속성 컨텍스트란 엔티티를 영구 저장하는 환경이라고 한다. 주로 버퍼링이나 캐싱 때문에 사용한다고...
이 영속성 컨텍스트로 인해 트랜젝션이 끝나는 시점에 최초 상태에서 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해준다.
이것이 바로 '더티 체킹(Dirty Checking)'!!
즉, JPA는 엔티티를 조회하면 그 상태 그대로 스냅샷을 만들어 둠 → 트랜젝션이 끝나는 시점에서 만들어둔 스냅샷과 비교 → 다른 점이 있다면 update 쿼리를 데이터베이스로 던짐
이런 상태 변경 검사는 영속성 컨텍스트가 관리하는 엔티티에만 적용된다.
= DB에 반영되기 전 처음 생성된 엔티티 반영 X
더디 체킹으로 생성되는 update 쿼리는 기본적으로 모든 필드가 업데이트 되는데, 전체 필드를 업데이트 할 때의 장점으로는
이 있다.
하지만 필드가 정말정말 많을 경우에는 전체 필드를 모두 업데이트 하게되면 당연히 성능이 떨어질 수 밖에 없다.
그러면 변경된 부분만 업데이트를 하면 되지 않을까?
다행히 그러한 기능을 @DynamicUpdate
가 지원한다고 한다.
@Getter
@NoArgsConstructor
@Entity
@DynamicUpdate
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
엔티티의 최상단에 해당 어노테이션을 붙여주면 해결!!