JPA 를 사용한 수정에서 save 메서드는 없어도 된다

박영준·2023년 7월 6일
1

JPA

목록 보기
8/8

1. 이유

JPA 의 영속성 컨텍스트변경 감지(Dirty Checking) 덕분이다.

이 둘이 있으므로, 수정(update) 시 save 메서드를 호출할 필요가 없다.

2. 동작 원리

순서 1 : Entity 조회

  • JPA 가 Entity 를 조회하면, 해당 Entity 안에 있는 정보들을 영속성 컨텍스트로 로딩한다
    • 처음 로드되면, 로드 된 상태의 초기 상태가 스냅샷으로 영속성 컨텍스트에 저장된다.

순서 2 : 영속성 컨텍스트가 감지

  • 트랜잭션 종료 시, 스냅샷과 현재 상태의 엔티티 객체를 비교 (변경 감지, 더티 체킹)

  • Entity 의 필드 값이 변경되면, 영속성 컨텍스트가 이를 감지한다

순서 3 : DB 에 자동 반영

  • 트랜잭션을 커밋할 때, 영속성 컨텍스트가 변경된 필드 값을 DB 에 자동 반영한다

  • 그리고, 메서드 종료 시 트랜잭션 커밋이 수행되면서, JPA flush 가 발동한다.

    • 이때, SQL 쿼리의 UPDATE 문을 자동 생성한다.
  • 단, 수정(update) 메서드에는 @Transactional 를 설정해둬야지만 메서드 반환 시점에 트랜잭션이 커밋된다

    • @Transactional 이 걸려있지 않다면, SELECT 쿼리만 발생하고 UPDATE 쿼리는 발생하지 않는다.

3. 예시

아래 코드는 게시글을 수정하는 메서드의 예시다.

save 메서드 사용 O

public BoardResponseDto updateBoard(Long id, BoardRequestDto requestDto) {
    Board board = findBoard(id);

    if (board.getPassword().equals(requestDto.getPassword())) {
        board.update(requestDto);
        boardRepository.save(board);		// save 메서드로 변경된 baord 엔티티를 저장
    } else {
        return new BoardResponseDto("비밀번호가 일치하지 않습니다.");
    }

    return new BoardResponseDto(board);
}

save 메서드 사용 X

@Transactional
public BoardResponseDto updateBoard(Long id, BoardRequestDto requestDto) {
    Board board = findBoard(id);

    if (board.getPassword().equals(requestDto.getPassword())) {
        board.update(requestDto);
    } else {
        return new BoardResponseDto("비밀번호가 일치하지 않습니다.");
    }

    return new BoardResponseDto(board);
}
  • save 메서드가 없는 대신, @Transactional 어노테이션을 달아주었다.
    • @Transactional 어노테이션을 메서드 위에 달아주는 방법을 '변경 감지(Dirty Checking)' 라고 한다.

참고: JPA 를 다시 공부하면서... 잡다한 정리...

profile
개발자로 거듭나기!

0개의 댓글