티스토리 뷰
✅ 더티 체킹(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 쿼리가 실행되는 것을 확인할 수 있습니다.
실행 순서는
- 트랜잭션이 시작 된다
- 업데이트하고 싶은 Board 엔티티를 조회한다
- "Content 변경"으로 Update를 진행줍니다
- 그 후 트랜잭션 커밋
✔ 이러한 과정이 더티 체킹입니다. 엔티티의 변경을 감지한 뒤 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은 하나의 테이블에 정말 많은 수의 컬럼이 있는데, 몇몇개의 컬럼만 자주 업데이트 하는 경우에 사용하시길 권장한다고 하네요.
참고 서적 : 혼자 구현하는 웹 서비스
'Spring Data JPA' 카테고리의 다른 글
JPA N+1 해결법 (1) | 2022.02.06 |
---|---|
JDBC VS Mybatis VS JPA (0) | 2021.12.13 |