티스토리 뷰

728x90

✅ 더티 체킹(Dirty Checking) 

트랜잭션 안에서 Enitity 변경이 일어났을 때 변경한 내용을 DB에 반영하는 것

 

더티 체킹 모를 때에는 Update 기능을 구현하기 위해서 아래와 같이 변경 부분만 다시 save 하는 코드를 작성했었다...

 

    @Transactional
    public Long boardUpdate(BoardUpdateDto dto) {
        Board origin = boardRepository.findById(dto.getId())
        Board update = InquiryAnswer.builder()
                .id(origin.getId())
                .content(dto.getContent())
                .build();
        return boardRepository.save(update).getId();
     }

혼자 구현하는 웹서비스를 보면 JPA는 별도로 데이터베이스에 save 하지 않는다. 라고 나와 있습니다.

그 이유는 더티 체킹 때문입니다.

 

아래 코드를 통해 확인하겠습니다.

BoardService.class

    @Transactional
    public void boardUpdateContent(Long id, String content) {
        Board board = boardRepository.findById(id)
                .orElseThrow(NotBoardException::new);
        board.updateContent(content);
    }

서비스 클래스에 Update 기능을 하는 비즈니스 로직을 작성할게요.

여기서 핵심이 Update를 하는 쿼리는 없습니다. 이 로직을 실행하면 DB에 Update가 잘 반영됩니다.

아래 테스트 코드를 실행해 보겠습니다.

@Test
void 더티체킹_실습() {
    //given
    board = boardRepository.save(new Board("content", member, categoryType));
    String content = "content 변경";

    //when
    Board origin = boardRepository.findById(board.getId()).get();
    origin.updateContent(content);

    //then
    assertThat(origin.getContent()).isEqualTo(content);
}

😯 save 메소드로 변경 사항을 저장하지 않고도 update 쿼리가 실행되는 것을 확인할 수 있습니다.

실행 순서는

  1. 트랜잭션이 시작 된다
  2. 업데이트하고 싶은 Board 엔티티를 조회한다
  3. "Content 변경"으로 Update를 진행줍니다
  4. 그 후 트랜잭션 커밋 

이러한 과정이 더티 체킹입니다.  엔티티의 변경을 감지한 뒤 DB에 반영시켜준다는 의미입니다. 추가적으로  더티 체킹을 검사하는 대상은 영속성 컨택스트가 관리하는 엔티티입니다. 비영속, 준영속 엔티티는 값을 변경해도 DB에 반영되지 않습니다.

 

 @DynamicUpdate 

위에서 봤듯이 저는 content 필드 하나만 변경했는데 모든 내용을 update 쿼리로 만들어 전달하게 됩니다.

이 현상이 일어나는 이유는 JPA에서는 전체 필드를 업데이트하는 방식을 기본값으로 사용하기 때문입니다.

만약 필드가 30개라면 불필요한 update 일 겁니다. 이것을 해결하는 방법은@DynamicUpdate 어노테이션을 사용하는 겁니다!!

 

 

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicUpdate //엔티티 클래스에 붙여주기
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "board_id")
    private Long id;

    private String title;

    private String content;
 }

어노테이션을 붙이고 Test를 진행해볼게요

보시다시피 content 부분만 update 쿼리가 나간 걸 확인할 수 있습니다!!

 

 

결론 : Jpa에는 update 코드를 작성하는 것이 없습니다. 저처럼 더티 체킹 몰랐을 때는 다시 save 하는 코드를 작성했는데 영속성 콘텍스트를 이해하신다면 더 바람직한 JPA 코드를 작성할 수 있을 것 같습니다.

추가적으로@DynamicUpdate은 하나의 테이블에 정말 많은 수의 컬럼이 있는데, 몇몇개의 컬럼만 자주 업데이트 하는 경우에 사용하시길 권장한다고 하네요.

 

참고 서적 :  혼자 구현하는 웹 서비스

출처 : https://www.baeldung.com/spring-data-jpa-dynamicupdate

'Spring Data JPA' 카테고리의 다른 글

JPA N+1 해결법  (1) 2022.02.06
JDBC VS Mybatis VS JPA  (0) 2021.12.13
댓글
최근에 달린 댓글
최근에 올라온 글
Total
Today
Yesterday
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30