반응형
(설명만 보려면 게시글 아래로)
게시글을 수정하는 코드를 작성하고 있다.
순서대로 Controller와 Service 코드의 일부이다.
@PutMapping("/api/v1/posts/{id}")
public Long update(@PathVariable Long id, @RequestBody PostsUpdateRequestDto requestDto) {
return postsService.update(id, requestDto);
}
@Transactional
public Long udpate(Long id, PostsUpdateRequestDto requestDto) {
Posts posts = postsRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id="+id));
posts.update(requestDto.getTitle(), requestDto.getContent());
return id;
}
Service에서 posts를 통해 update를 호출했는데 이것은 내가 Posts라는 객체에서 직접 선언해준 부분이다.
public void update(String title, String content) {
this.title = title;
this.content = content;
}
어떤 점이 의아하냐 하면, 코드 내에서 쿼리를 날리는 부분이 없다.
하지만 테스트 코드를 작성해서 확인해보면 update문이 실행된 것을 확인할 수 있다.
...
@Test
public void Posts_수정() throws Exception {
//given
Posts savedPosts = postsRepository.save(Posts.builder()
.title("title")
.content("content")
.author("author")
.build());
Long updateId = savedPosts.getId();
String expectedTitle = "title!!";
String expectedContent = "content!!";
String url = "http://localhost:" + port + "/api/v1/posts/" + updateId;
PostsUpdateRequestDto requestDto = PostsUpdateRequestDto.builder()
.title(expectedTitle)
.content(expectedContent)
.build();
HttpEntity<PostsUpdateRequestDto> requestEntity = new HttpEntity<>(requestDto);
//when
ResponseEntity<Long> responseEntity = restTemplate
.exchange(url, HttpMethod.PUT, requestEntity, Long.class);
//then
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(responseEntity.getBody()).isGreaterThan(0L);
List<Posts> all = postsRepository.findAll();
assertThat(all.get(0).getTitle()).isEqualTo(expectedTitle);
assertThat(all.get(0).getContent()).isEqualTo(expectedContent);
}
...
이는 Dirty Checking 덕분인데, 상태 변경 검사 정도로 이해하면 된다.
JPA에서 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 db에 자동으로 반영해준다.
(변화가 있다의 기준: 최초 조회 상태)
JPA에서는 엔티티를 조회하면 해당 엔티티의 조회 상태 그대로 스냅샷을 만들어둔다.
트랜잭션이 끝나는 시점에 이 스냅샷과 비교하고 다른 점이 있다면 Update Query를 db로 전달한다.
이런 Dirty Checking의 대상은 '영속성 컨텍스트가 관리하는 엔티티'만 적용된다.
detach된 엔티티(준영속), db 반영 전의 첫 생성 엔티티(비영속) 등의 엔티티는 적용 대상이 아니다.
(=값을 변경해도 db에 반영되지 않는다)
Dirty Checking의 update 쿼리는 모든 필드 업데이트가 디폴트다.
변경 부분만 update하고 싶다면 엔티티 최상단에 @DynamicUpdate를 선언해주면 된다.
참고
- 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 / 이동욱
반응형
'Develop > Java' 카테고리의 다른 글
[Java] String, StringBuffer, StringBuilder (0) | 2021.02.02 |
---|---|
[java] this와 this() (0) | 2021.01.26 |
역할, 책임, 협력 관점으로 객체지향 살펴보기 (0) | 2021.01.15 |
[Java] 시간 구하는 방법 비교 (0) | 2021.01.14 |
[Java] The type java.??? cannot be resolved. It is indirectly referenced from required .class files (0) | 2021.01.08 |