인프런 커뮤니티 질문&답변

Jaesang Yoon님의 프로필 이미지

작성한 질문수

실전! 스프링 데이터 JPA

벌크성 수정 쿼리

Spring Data JPA에서 update 하는 방법

작성

·

1.5K

0

검색해보니 Spring Data JPA는 순수 JPA와 다르게 save() 조차 하지 않아도 자동으로 변경감지가 일어난다고하는데, 제가 작성한 코드를 바탕으로 테스트해보니 save()를 하지 않으면 업데이트가 되지 않았습니다. 조금 더 디테일한 설명을 해주실 수 있을까요?

save()는 @PostMapping의 postRepository.save(findPost); 부분을 지칭하는 것입니다.

@Controller
@RequestMapping("/post")
@RequiredArgsConstructor
@Slf4j
public class PostController {

    private final BoardService boardService;
    private final BoardRepository boardRepository;
    private final PostService postService;
    private final PostRepository postRepository;

    /**
     * 게시물 수정
     */
    @GetMapping("/edit/{id}")
    public String showEdit(@PathVariable Long id, @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) {

        Post findPost = boardRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("No Post Found."));// findPost 게시물 보여주기

        model.addAttribute("findPost", findPost);

        return "editPost";
    }

    @PostMapping("/edit/{id}")
    public String editPost(@PathVariable Long id, Post editPost) {

        Post findPost = boardRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("No Post Found."));

        findPost.setTitle(editPost.getTitle());
        findPost.setContent(editPost.getContent());
        findPost.setCategory(editPost.getCategory());
        findPost.setLastModifiedTime(LocalDateTime.now());

        postRepository.save(findPost);

        return "redirect:/board/post/" + id;
    }
   
}



public interface PostRepository extends JpaRepository<Post, Long> {

    /**
     * 게시물 저장
     */
    Post save(Post post);

}

 

 



답변 2

0

안녕하세요. Jaesang Yoon님, 공식 서포터즈 David입니다.

변경감지를 활용하려면 영속성 컨텍스트에서 관리되고 있는 엔티티여야 합니다.

현재 별도로 트랜잭션을 묶지 않고findById를 통해 Post를 찾아오면 준영속 상태가 됩니다.

따라서, 변경감지가 동작하지 않게 됩니다.

@Transcational을 사용하여 조회와 수정이 발생하는 메서드를 하나의 트랜잭션으로 묶어주세요.

감사합니다.

Jaesang Yoon님의 프로필 이미지
Jaesang Yoon
질문자

답변 감사합니다.

그런데 findById로 가져온 엔티티는 준영속이 아닌 영속상태의 엔티티 아닌가요??

제가 OSIV에 대한 설명을 빠뜨렸네요.

OSIV가 켜져있으면 이해하신 게 맞습니다.

실무에서는 주로 성능 문제로 OSIV를 끈 채로 사용합니다.

아래 답변을 참고해 주세요.

https://www.inflearn.com/questions/880832/comment/262423

0

안녕하세요, 인프런 AI 인턴입니다.

Jaesang Yoon님의 질문에 대해, Spring Data JPA에서 save() 메소드의 역할과 업데이트 처리 방식에 대해서 설명드리겠습니다.

Spring Data JPA의 save() 메소드

Spring Data JPA에서 save() 메소드는 엔티티의 상태에 따라 persist (새로운 엔터티 저장) 또는 merge (기존 엔터티 업데이트)를 내부적으로 호출합니다. 즉, 엔터티의 식별자 값이 null이거나 존재하지 않는 경우 새로운 엔터티로 간주하여 persist를 호출하고, 식별자 값이 존재하는 경우에는 merge를 호출하여 업데이트를 수행합니다.

변경 감지(Dirty Checking)

변경 감지는 엔터티가 영속성 컨텍스트에 의해 관리되는 상태(영속 상태)에서, 트랜잭션이 끝나는 시점에 엔터티의 변경 사항을 데이터베이스에 반영하는 기능입니다. 이는 @Transactional 어노테이션이 붙은 서비스 레이어에서 주로 발생합니다. 따라서, 영속 상태의 엔터티를 수정하는 경우 별도의 save() 호출 없이도 변경 사항이 데이터베이스에 반영될 수 있습니다. 하지만 이때, 엔터티가 영속 상태여야 한다는 점이 중요하며, Controller에서 직접 엔터티의 상태를 변경하는 경우 영속성 컨텍스트 밖에서 이루어지기 때문에 save()를 호출해야 업데이트가 반영됩니다.

관련 질문 링크

이 링크에서는 Spring Data JPA의 save() 메서드가 중복되는 id 값이 들어갈 경우 update 문을 자동으로 수행하는 이유에 대해 설명하고 있습니다. save()를 호출해야 하는 상황과 그 원리에 대해 나와있는 정보가 Jaesang Yoon님의 질문에 도움이 될 수 있을 것 같습니다.

위 설명을 바탕으로, 컨트롤러에서 변경 사항을 데이터베이스에 반영하고자 할 때는 변경 사항을 적용한 후 명시적으로 save()를 호출하여 엔터티의 변경 사항을 영속화해야 함을 알 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.