SpringBoot

[SpringBoot] Transaction 커밋 적용

코카멍멍 2023. 4. 20. 15:39
반응형
  1. 오늘의 문제: Transaction
  2. 내 코드 분석

Transaction

오늘 코딩하면서 게시글을 수정하는 단계에서 updated_at 수정 필드가 업데이트가 되지 않아서 찾아보게 됐다.

@Transactional
    public Post modify(String title, String body, String username, Integer postId) {
        // 포스트 찾기
        log.info("포스트 찾기");
        PostEntity postEntity = postRepository.findById(postId).orElseThrow(() -> 
        new SnsException(Errorcode.NOT_EXISTS_POST, String.format("게시글 ID: %d", postId)));
        
        // 생성자, 수정자 일치 확인
        log.info("생성자 수정자 일치");
        
        if (!Objects.equals(postEntity.getMember().getName(), username)){
            throw new SnsException(Errorcode.INVALID_PERMISSION, 
            String.format("생성자: %s \n 수정자: %s", postEntity.getMember().getName(), username));
        }
        
        postEntity.setTitle(title);
        postEntity.setBody(body);
        PostEntity save = postRepository. save(postEntity);

        return Post.fromEntity(save);
    }

 

PostEntity의 값을 수정하고 JpaRepository의 save 메소드를 이용해서 저장 하고 업데이트 된 값을 확인하려고 했지만 실제 출력되는 값은 null이 반환 되었다. 그래서 이 것을 해결하기 위해서 찾아보기로 했다.

 

먼저 save() 메소드와 saveAndFlush() 메소드에 대해서 알아 봐야할 것 같다.

 

save VS saveAndFlush

save()의 메소드 특징은 영속성 컨텍스트를 저장하고 Transaction 커밋이 끝나야지만 DB에 flush()가 된다.

saveAndFlush() 메소드는 영속성 컨텍스트를 저장하고 바로 DB에 flush()하는 것을 의미한다.

flush()는 영속성 컨텍스트에 있는 데이터를 DB에 적용하는 과정을 의미한다.

 

만약 save 메소드를 이용한다면 아래와 같은 상황에서 flush()가 발생한다.

  1. 트랜잭션 커밋 시
  2. JPQL 쿼리 실행 시
  3. flush() 메소드 호출 

 

 

내 코드에서 문제점 발견하기

        PostEntity save = postRepository. save(postEntity);

        return Post.fromEntity(save);

문제가 발생하는 부분을 발췌해 왔다.

해당 메소드가 끝나기 전에 PostEntity -> Post(DTO)로 변환하기 때문에 아직 updated_at이 적용되지 않은 PostEntity의 updated_at 값이 Post에 전달 된 것이다.

그렇기에 문제점을 해결하기 위해서는 flush() 메소드를 사용하거나, saveAndFlush() 메소드를 사용하여 해결할 수 있다.

반응형