어떤 데이터나 상태가 마지막으로 확인된 후, 변경된 부분이 있다면 자동으로 트랜잭션이 끝나는 시점에 데이터베이스에 반영하는 기능이다.
dirty 란 "entity data의 변경된 부분"을 뜻한다.
영속성 컨텍스트가 관리하는 영속 상태의 엔티티만 적용된다. 준영속/비영속 상태의 엔티티는 더티 체킹을 할 수 없다.
트랜잭션이 커밋될 때 엔티티의 변경된 상태를 DB에 반영한다. 커밋 전까지는 상태를 추적만 한다.
update 에 관련된 쿼리를 작성하지 않아도 되기 때문에, 코드의 복잡성을 줄일 수 있다.
@Entity
public class User {
@Id
private Long id;
private String username;
private String email;
// Getters and setters
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void updateUsername(Long userId, String newUsername) {
// 트랜잭션 내에서 엔티티를 가져와 상태를 변경
User user = userRepository.findById(userId).orElse(null);
if (user != null) {
// Dirty Checking을 통한 엔티티 상태 변경
user.setUsername(newUsername);
}
// 트랜잭션 커밋 시 Dirty Checking 발생
// 트랜잭션 종료 시 엔티티 상태 변경사항이 데이터베이스에 반영됨
}
}
메소드가 호출될 때 트랜잭션 시작
userRepository.findById(userId)
는 userId 에 해당하는 User 엔티티를 DB에서 가져온다.
setUsername
메소드를 호출하여 엔티티의 username 속성을 변경한다.
이 시점에서 엔티티의 상태가 Dirty 로 표시된다. (트랜잭션 범위 내에서 수정되었기 때문)
@Transactional
은 메소드가 정상적으로 완료되면 트랜잭션을 자동으로 커밋하고, 이 단계에서 Dirty Checking 이 수행
Hibernate 는 영속성 컨텍스트 내의 엔티티의 현재 상태와 초기 상태를 비교한다.
변경 사항이 감지되면 Hibernate 는 DB에 변경 사항을 동기화하기 위한 SQL 문을 생성한다. 이 경우에는 새 username 을 반영하기 위해 UPDATE 문이 실행
Dirty Checking 은 주로 트랜잭션이 커밋될 때 이루어진다.
Entity를 영속성 컨텍스트에 보관할 때, 최초의 상태를 복사해서 저장해둔다. (스냅샷)
영속성 컨텍스트의 변경 내용을 DB에 반영한다. (플러시)
플러시 시점에 스냅샷과 Entity를 비교해서 변경된 Entity를 찾는다.