-
Dirty Cheking을 잘못 사용한 경우SpringBoot 2023. 8. 2. 12:03
간단한 update작업중 dirty checking이 안되는 문제가 발생했습니다.
문제의 코드는 다음과 같습니다.
public Member updateUserNickname(PutUserNicknameRequest request, Member member){ member.updateUserNickname(request.getNickname()); return member; }
위의 코드는 nickname을 받아서 update하는 목적으로 코드가 작성되었으나 db에 제대로 업데이트가 되지 않는 문제가 발생했습니다. 따라서 왜 이런 문제가 발생했는지 찾아보았습니다.
더티 체킹(Dirty Checking)이란?
- JPA는 엔티티 매니저가 엔티티를 저장/조회/수정/삭제를 합니다.
- 그런데 엔티티 매니저의 메서드를 찾아보면, 저장/조회/수정/삭제로 수정에 해당하는 메서드가 없습니다.
- 대신에 수정에 해당하는 더티 체킹(Dirty Checking)을 지원합니다.
- 더티 체킹은 Transaction 안에서 엔티티의 변경이 일어나면, 변경 내용을 자동으로 데이터베이스에 반영하는 JPA 특징입니다.
- 데이터베이스에 변경 데이터를 저장하는 시점 : 1) Transaction commit 시점 2) EntityManager flush 시점 3) JPQL 사용 시점
- 또한, 영속성 컨택스트(Persistence Context) 안에 있는 엔티티를 대상으로 더티 체킹이 일어납니다.
- 여기서 Dirty란 "엔티티 데이터의 변경된 부분"으로 해석하시면 됩니다. 즉, 변경된 부분을 체크해서 DB에 반영한다는 뜻으로 해석합니다.
JPA 영속성 컨텍스트
더티 체킹이 일어나는 환경은 아래 두 가지 조건이 충족되어야 합니다.
- 영속 상태(Managed) 안에 있는 엔티티인 경우
- Transaction 안에서 엔티티를 변경하는 경우
저의 경우에는 2가지 모두 만족하지 못했습니다.
해당 코드는 Transaction상태가 아니었으며, 영속 상태의 엔티티 또한 아니었습니다.
위의 코드에서 @Transactional를 붙이더라도 영속상태가 아니므로 db에 업데이트가 원활하게 되지 않았던 것입니다.
해당 코드를 Dirty Checking을 사용하기 위해 수정한다면 다음과 같습니다.
@Transactional public Member updateUserNickname(PutUserNicknameRequest request, Long id){ Member member = memberRepository.findById(id); member.updateUserNickname(request.getNickname()); return member; }
'SpringBoot' 카테고리의 다른 글
배열의 공변성 (0) 2025.02.13 Spring Boot에서 동시성 처리 문제 해결하기: 예약 승인 기능 개발기 (0) 2024.11.07 Ramdom vs SecureRandom vs ThreadLocalRandom (0) 2024.06.18 Docker로 AWS EC2 배포하기 (0) 2023.08.02 자바 스크래핑 (0) 2023.05.01