2022. 4. 21. 15:24ㆍWeb/Spring
소비자가 업로드한 사진과 글에 대해 댓글을 관리하고 댓글을 수정하는 기능을 구현 중이다.
JpaRepository에서 crud를 간편하게 하는 메소드를 지원 중이라 해서 사용하였으니 이를 더 적극적으로 활용하면 좋지 않을까 하는 생각이 들었다.
그래서 우선 공식 doc에 들어가서 한번 찾아보기로 했다.
JpaRepository (Spring Data JPA 2.6.4 API)
getById T getById(ID id) Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is implemented this is very likely to always return an instance and throw an EntityNotFoundException on first access. Some
docs.spring.io
메소드를 쭉 살펴봤더니 딱 봐도 업데이트(put) 기능이다 하는 메소드는 안보였다.
save를 통해 Update를 하는건가? 어떻게? 생각을 했고, 검색을 해보니 어떤 블로그에 적혀져 있는 PutMapping을 통해 데이터를 업데이트 하는 걸 살펴봤다. 한 필드마다 하나씩 set에서 get을 통해 가져온 데이터를 넣어준다고 한다.
이게 맞나..? 싶었지만 일단 코드를 작성했고, 다음과 같았다.
// 댓글 수정
@Transactional
public void updateComment(Long id, String content) {
Comment comment = commentRepository.getById(id);
comment.setConsumer(comment.getConsumer());
comment.setPost(comment.getPost());
comment.setId(comment.getId());
comment.setContent(content);
commentRepository.save(comment);
}
여기까지는 노가다지만 그냥 그렇구나 하고 넘길 수 있는 상황이긴 했는데 상품을 장바구니에 담는 과정에서 다시 한번 생각해보게 되었다. 상품을 장바구니에 담을 때 status를 바꿔야 하는데 상품 필드가 너무 많았다.
set을 통해 get으로 가져온 데이터를 다시 넣고 한다...? 너무 번거롭다. 복붙은 괜찮지만 분명히 다른 방법이 있을거 같다는 생각이 들었다. 그래서 조금 더 찾아보기로 한다. 더 검색을 해보니 JPA에서는 Dirty Checking을 지원을 하기에 update할 때 일일히 set get을 해줄 필요가 없다는 사실을 알게 되었다.
이를 더 잘 이해하기 위해서는 JPA의 영속성 개념을 잘 이해하고 있을 필요가 있다. JPA는 Java Persistence API의 약자로 Java에서 지원하는 표준 API이다. JPA의 가운데에 있는 Persistence가 바로 영속성으로 어떤 프로그램이 데이터를 생성하고 종료하였을 때 데이터는 사라지지 않는 특성을 말한다. JPA에서는 EntityManager에 따라서 데이터를 저장할지 그렇지 않을지 결정이 된다고 한다.
조사하면서 하나 알게된 게 있는데 Spring Data JPA를 사용하면 자동적으로 EntityManager가 활성화되어 있는 상태라 한다. 처음에 이 부분을 몰라 EntityManager를 설명하는 예제를 보면서 계속 선언하여 사용했는데, 그렇게 안해도 매니저가 자동적으로 생성된 상태로 사용할 수 있는 거였다.
하여튼 Dirty Checking이란 Transaction 속에 있는 엔티티에 변화가 있다면 그 변화를 감지하여 자동적으로 데이터베이스에 반영한다는 뜻이라 한다. 위에서 작성한 방법처럼 set get 하지 않아도 자동적으로 변화된 부분을 감지해서 전체를 update문을 통해 업데이트를 실행한다고 한다.
Spring에서는 자동적으로 EntityManager를 만들어주니까 변경된 부분만 set해주고, save() 해주면 되나? 생각이 들었다.
일단 @Transactional 아래 부분을 다시 고쳐보도록 하겠다.
// 댓글 수정
@Transactional
public void updateComment(Long id, String content) {
Comment comment = commentRepository.getById(id);
// comment.setConsumer(comment.getConsumer());
// comment.setPost(comment.getPost());
// comment.setId(comment.getId());
comment.setContent(content);
commentRepository.save(comment);
}
굳이 set을 할 필요가 없다니까 세 줄을 주석친다.
일단 form에 넣어서 해보겠다.
'Web > Spring' 카테고리의 다른 글
[JPA] Hibernate 오류 : failed to lazily initialize a collection of role (0) | 2022.05.17 |
---|---|
[JPA] 댓글 수정하기 기능 - @RequestBody, @ModelAttribute (2) (0) | 2022.04.22 |
[Spring Boot] Thymeleaf onclick 설정 (0) | 2022.04.19 |
[JPA] 쇼핑몰 - 댓글/좋아요 카운트 (N+1, Fetch Join, @Formula) (0) | 2022.04.16 |
[JPA] The given id must not be null! 에러 (0) | 2022.04.15 |