🕶 업데이트 기능을 만들어 봅시다!.
- Controller 클래스에 기능 추가해보기!
@PutMapping("/api/v1/posts/{id}") -> http put() 사용합니다.
public Long update(@PathVariable Long id, @RequestBody PostsUpdateRequestDto requestDto) {
    return postsService.update(id, requestDto);
}
updateRequestDto 클래스를 활용하여 업데이트 할 데이터를 담아서 엔티티에 전달하게 합니다.
- updateRequestDto 클래스 생성해보기!
@Getter
@NoArgsConstructor
public class PostsUpdateRequestDto{
    private String title;
    private String content;
    @Builder
    public PostsUpdateRequestDto(String title, String content) {
        this.title = title;
        this.content = content;
    }
}
- Service 클래스에 update() 기능 추가해보기!
@Transactional
public Long update(Long id, PostsUpdateRequestDto requestDto) {
    Posts entity = getEntity(id);
    entity.update(requestDto.getTitle(), requestDto.getContent());
    return entity.getId();
}
트랜잭션 실패로 인해 데이터의 무결성과 지속성 영속성을 보장하기 위해 @Transactional 를 사용합니다.
코드를 보면 업데이트를 하는 쿼리문은 보이질 않습니다.
😭 쿼리문이 없는데 업데이트가 어떻게 되나요????
JPA 의 영속성 컨텍스트 의 특징으로 업데이트 쿼리문을 안날려도 업데이트가 됩니다. 영속성 컨텍스트 란 엔티티를 영구 저장하는 환경 이라고 합니다.
JPA 의 엔티티 매니저가 활성화 된 상태 (Spring Data JPA 를 사용하면 디폴트 값이 활성 상태입니다.) 로 트랜잭션에서 데이터베이스에서 데이터를 가져오면 이 데이터는 영속성 컨텍스트가 유지된 상태입니다.
이 상태에서 해당 데이터의 값을 변경하면 트랜잭션이 끝나는 시점에 해당 테이블에 반영이 되어 업데이트 쿼리문을 날리지 않아도 업데이트가 될 수 있는 겁니다.
- Entity 클래스에 update() 기능 추가!!
public void update(String title, String content) {
    this.title = title;
    this.content = content;
}
- getEntity() 살펴보기!
private Posts getEntity(Long id) {
    return postsRepository.findById(id)
            .orElseThrow(()-> new IllegalArgumentException("존재하는 게시글이 없습니다."));
}
findById() 기능에서도 중복된 코드를 사용하므로 메서드를 따로 추출하여 리펙토링을 하였습니다.
🕶 테스트 코드를 작성해봅시다.
- updateRequestDto 클래스 테스트
@Test
@DisplayName("PostsUpdateRequestDto_TEST")
void PostsUpdateRequestDtoTest() {
    // given
    String expectedTitle = "테스트";
    String expectedContent = "테스트 중 입니다.";
    // when
    PostsUpdateRequestDto requestDto = PostsUpdateRequestDto.builder()
                    .title("테스트")
                    .content("테스트 중 입니다.")
                    .build();
    // then
    assertThat(requestDto.getTitle()).isEqualTo(expectedTitle);
    assertThat(requestDto.getContent()).isEqualTo(expectedContent);
}
- Service 클래스 update 테스트
    @BeforeEach
    public void beforeEach() {
        PostsSaveRequestDto dto = PostsSaveRequestDto.builder()
                .title("테스트1")
                .content("테스트 중 입니다.1")
                .author("홍길동1")
                .build();
        postsService.save(dto);
    }
    @AfterEach
    public void afterEach() {
        postsRepository.deleteAll();
    }
    @Test
    @DisplayName("Update_된다")
    void update() {
        // given
        Long findId = 1L;
        String expectedTitle = "테스트 수정";
        String expectedContent = "테스트 중 입니다. 수정";
        PostsUpdateRequestDto updateRequestDto = PostsUpdateRequestDto.builder()
                            .title(expectedTitle)
                            .content(expectedContent)
                            .build();
        // when
        postsService.update(findId, updateRequestDto);
        // then
        PostsResponseDto updatePosts = postsService.findById(1L);
        assertThat(updatePosts.getTitle()).isEqualTo(expectedTitle);
        assertThat(updatePosts.getContent()).isEqualTo(expectedContent);
}
테스트 코드가 실행 되기 전에 domain 의 데이터 값을 저장 하여 update 기능을 검증 합니다.
- Controller 클래스 테스트
@BeforeEach
public void beforeEach() {
    postsRepository.save(PostsSaveRequestDto.builder()
                .title("테스트1")
                .content("테스트 중 입니다.1")
                .author("홍길동1")
                .build()
                .toEntity());
}
@AfterEach
public void afterEach() {
    postsRepository.deleteAll();
}
@Test
@DisplayName("Update_된다!!!!")
void update() {
    // given
    Posts posts = postsRepository
            .findById(1L)
            .orElseThrow(()-> new IllegalArgumentException("존재하지 않습니다."));
    Long updatedId = posts.getId();
    String expectedTitle = "테스트2";
    String expectedContent = "테스트 중 입니다.2";
    PostsUpdateRequestDto requestDto = PostsUpdateRequestDto.builder()
            .title(expectedTitle)
            .content(expectedContent)
            .build();
    String url = "<http://localhost>:" + port + "/api/v1/posts/" + updatedId;
    HttpEntity<PostsUpdateRequestDto> postsUpdateRequestDtoHttpEntity =
            new HttpEntity<>(requestDto);
    // when
    ResponseEntity<Long> responseEntity =
            restTemplate.exchange(url, HttpMethod.PUT, postsUpdateRequestDtoHttpEntity, 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);
}
테스트 코드가 실행 되기 전에 domain 의 데이터 값을 저장 하여 update 기능을 검증 합니다.
🕶 로그를 살펴보자!

업데이트 쿼리가 실행 되는 것을 살펴 볼 수 있습니다.!
'Book > Spring boot 와 AWS로 혼자 구현하는 웹서비스' 카테고리의 다른 글
| [Book] 15) 머스테치로 화면 구성을 해보자! -2 (0) | 2022.04.01 | 
|---|---|
| [Book] 14) 머스테치로 화면 구성을 해보자! -1 (0) | 2022.04.01 | 
| [Book] 13) JPA Auditing으로 생성시간/수정시간 자동화 하기! (0) | 2022.04.01 | 
| [Book] 12) H2 DB 웹 콘솔에서 직접 접근해보자! (0) | 2022.04.01 | 
| [Book] 10) API 만들어보기! -3 (0) | 2022.03.31 | 
| [Book] 9) API 만들어보기! - 2 (0) | 2022.03.30 | 
| [Book] 8) API 만들어보기! - 1 (0) | 2022.03.30 | 
| [Book] 7) 출력되는 쿼리문을 MySQL 문법으로 수정 후 이슈 (0) | 2022.03.30 | 
![[Book] 11) API 만들어보기! -4](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdna%2FcoCH4M%2Fbtrx6ZBKdM2%2FAAAAAAAAAAAAAAAAAAAAAMZ1MMih4w2WmVRfEAesq2J7r3A84EMhadLdVQ35MN9d%2Fimg.png%3Fcredential%3DyqXZFxpELC7KVnFOS48ylbz2pIh7yKj8%26expires%3D1761922799%26allow_ip%3D%26allow_referer%3D%26signature%3D0agI32e83cfuxOr0HtHPLd%252FPJPw%253D)