ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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;
    }
Designed by Tistory.