게시판 조회 등록 수정 삭제 만들기

존스노우·2021년 9월 27일
0

3개의 클래스가 추가로 만듬.

Request 데이터 받을 Dto
Api 요청받을 controller
트랜잭션, 도메인 기능간의 순서 보장하는 Service

여기서 비즈니스 로직을 담당하는 부분은 Domain 부분

mybatis에서는 api 를 짤때 서비스부분에서 비즈니스로직을 많이 구현했다

하지만 JPA에서는 서비스부분은 단지 트랜잭션 역활 실행만 하는부분이라
객체의 메세지를 보내서 상태값을 수정한뒤 처리하고(메소드호출) 리턴하는 방식이다.

PostsApi 컨트롤러다. 경로에따른 데이터를 출력해준다 . controller -> service -> repository(구현체없음)

save 할때는 saveRequestDto 따로 UpdateDto 따로 구현해주는 특징이있다.

(@RequiredArgsConstructor)
기존 프로젝트에선 Autowird로 의존성을 주입해줬는대 여기선 생성자 방식으로 의존성을 주입해줬다.

saveDTo 코드부분이다 Entity 클래스와 유사하지만 절대로 request/respons 클래스로 사용하면 안됨!
데이터와 맞닿은 핵심클래스는 ENtitiy class 이기때문에 분리해줘야됨!

서비스 부분 여기서도 생성자 주입 방식으로 의존성 주입.(@RequireArgumentConstructor에서
해줌 final이 선언된 필드를 인자값으로 하는)
레파지토리와 연결되 아이디를 조회 하거나 save update delete 등을 트랜잭션으로 구분해놨다.
그리고 생성자를 BUILD 방식으로 구현했다.

package com.bookStudy.boo.springboot.web;

import com.bookStudy.boo.springboot.domain.posts.Posts;
import com.bookStudy.boo.springboot.domain.posts.PostsRepository;
import com.bookStudy.boo.springboot.web.dto.PostUpdateRequestDto;
import com.bookStudy.boo.springboot.web.dto.PostsSaveRequestsDto;
import javafx.geometry.Pos;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PostsApiControllerTest {

@LocalServerPort
private int port;

@Autowired
private TestRestTemplate restTemplate;

@Autowired
private PostsRepository postsRepository;

@After
public void tearDown() throws Exception {
    postsRepository.deleteAll();
}

@Test
public void 등록() {

    String title = "title";
    String content = "content";

    PostsSaveRequestsDto requestsDto = PostsSaveRequestsDto.builder()
            .title(title)
            .content(content)
            .author("author")
            .build();
    String url = "http://localhost:" + port + "/api/v1/posts";


    ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url, requestsDto, Long.class);

    assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
    assertThat(responseEntity.getBody()).isGreaterThan(0L);

    List<Posts> all = postsRepository.findAll();
    assertThat(all.get(0).getTitle()).isEqualTo(title);
    assertThat(all.get(0).getContent()).isEqualTo(content);
}


@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 = "title2";
    String expectedContent = "content2";


    PostUpdateRequestDto requestDto = PostUpdateRequestDto.builder().tilte(expectedTitle)
                                                                    .content(expectedContent).build();

    String url = "http://localhost:" +port + "/api/v1/posts/" + updateId;

    HttpEntity<PostUpdateRequestDto> 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);
}

}

컨트롤러 테스트 부분 ..

흠...

update 부분에선 쿼리를 날리지않는다.

이유는 JPA 영속성 컨텍스트 때문이다. -> 엔티티를 영구저장하는 환경.

트랜잭션안에서 데이터베이스에서 데이터를 가져와서 링크된 엔티티(Posts)에 저장되면

이엔티티데이터는 영속성 컨텍스트가 유지가 된다.

그래서 Posts 엔티티안에 update 메소드 함수를 만들어주고 상태를 변경해주기만 하면.

트랜잭션이 끝나면 해당 데이터를 테이블에 반영한다.

더티체킹이라고 하는 이개념은 엔티티객체의 값만 변경하면 Update쿼리를 날릴 필요가 없다.

공통으로 저장시간 변경시간을 따로 엔티티로 뺀다. (Posts entity extend)

이부분은 extend로 연결하면 save update시 자동 반영되는듯?

profile
어제의 나보다 한걸음 더

0개의 댓글