goblin
리니팅
goblin

공지사항

전체 방문자
오늘
어제
  • 분류 전체보기 (75)
    • 개발 (31)
      • Spring (12)
      • JPA (4)
      • JAVA (4)
      • Python (6)
      • Docker (1)
      • Error (3)
      • Spring Cloud로 개발하는 MSA (1)
    • 알고리즘 (32)
    • 자료구조 (3)
    • 컴퓨터 개론 (3)
    • 개인 프로젝트 (4)
      • 쇼핑몰 만들기 (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

태그

  • 다이나믹프로그래밍
  • 파워자바
  • 파이썬
  • dp
  • 프로그래머스
  • inflearn
  • 정렬
  • 구현
  • tdd
  • 알고리즘
  • python
  • 문자열
  • 객체
  • sorting
  • 코딩테스트
  • springboot
  • Intellij
  • 동적계획법
  • 스프링부트
  • 자료구조
  • Spring
  • BOJ
  • 다이나믹 프로그래밍
  • gradle
  • 백준
  • 클래스
  • 코딩테스트연습
  • JPA
  • 스프링
  • 조합

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
goblin

리니팅

CRUD API
개발/Spring

CRUD API

2022. 7. 7. 18:31
728x90

저는 도메인 모델을 사용하여 앞으로 코드를 작성하겠습니다!

https://arinlee.tistory.com/60

 

[Spring Boot] 도메인 계층에서 비즈니스 로직 처리

Spring Web 계층 Web Layer Controller, JSP/Freemarker 등의 뷰 템플릿 영역 이외에도 필터, 인터셉터, 컨트롤러 어드바이스 등 외부 요청과 응답에 대한 전반적인 영역 Service Layer @Service에 사용되는 서비..

arinlee.tistory.com

이 글을 참고해 주세요.

 

등록(Create)

1. PostsApiController

@RequiredArgsConstructor
@RestController
public class PostsApiController {

    private final PostsService postsService;

    @PostMapping("/api/v1/posts")
    public Long save(@RequestBody PostsSaveRequestDto requestDto){
        return postsService.save(requestDto);
    }
}

 

2. PostsService

@RequiredArgsConstructor
@Service
public class PostsService {
    private final PostsRepository postsRepository;

    @Transactional
    public Long save(PostsSaveRequestDto requestDto){
        return postsRepository.save(requestDto.toEntity()).getId();
    }
}

 

스프링에서 Bean을 주입하는 방식

  • @Autowired
  • setter
  • 생성자(권장)

위 코드에서 생성자는 @RequiredArgsConstructor에서 해결한다.

final이 선언된 모든 필드를 인자값으로 하는 생성자를 롬복의 @RequiredArgsConstructor가 대신 생성

why?

    해당 클래스의 의존성 관계가 변경될 때마다 생성자 코드를 계속해서 수정하는 번거로움을 해결하기 위함 (롬복 어노테이션이 있으면 생성자 코드는 손대지 않아도 됨)

 

3. PostsSaveRequestDto

@Getter
@NoArgsConstructor
public class PostsSaveRequestDto {
    private String title;
    private String content;
    private String author;

    @Builder
    public PostsSaveRequestDto(String title, String content, String author){
        this.title = title;
        this.content = content;
        this.author = author;
    }

    public Posts toEntity(){
        return Posts.builder()
                .title(title)
                .content(content)
                .author(author)
                .build();
    }
}

Entity와 유사한 형태의 Dto 클래스를 추가로 만들었다. 

Entity 클래스는 DB와 맞닿은 핵심 클래스이다. Entity 클래스를 기준으로 테이블이 생성되고, 스키마가 변경된다.

수많은 클래스 서비스나 비즈니스 로직들이 Entity 클래스를 기준으로 동작 → Entity가 변경되면 여러 클래스에 영향을 미는 반면 Request와 Response용 Dto는 View를 위한 클래스라 잦은 변경 필요

 

View Layer와 DB Layer의 역할 분리!!

→Entity 클래스와 Controller에서 쓸 Dto는 분리해서 써야한다.

 

4. 테스트

@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 Posts_등록() throws Exception{
        //given
        String title = "title";
        String content = "content";
        PostsSaveRequestDto requestDto = PostsSaveRequestDto.builder()
                .title(title)
                .content(content)
                .author("author")
                .build();

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

        //when
        ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url,requestDto,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(title);
        assertThat(all.get(0).getContent()).isEqualTo(content);
        }
    }

 

5. 실행 결과

insert 쿼리가 실행된 것 확인

 

수정, 조회

1. PostsApiController

@PutMapping("/api/v1/posts/{id}")
public Long update(@PathVariable Long id, @RequestBody PostsUpdateRequestDto requestDto){
    return postsService.update(id, requestDto);
}

@GetMapping("/api/v1/posts/{id}")
public PostsResponseDto findById(@PathVariable Long id){
    return postsService.findById(id);
}

 

2. PostsResponseDto

@Getter
public class PostsResponseDto {

    private Long id;
    private String title;
    private String content;
    private String author;

    public PostsResponseDto(Posts entity){
        this.id = entity.getId();
        this.title = entity.getTitle();
        this.content = entity.getContent();
        this.author = entity.getAuthor();
    }
}

PostsResponseDto는 Entity의 필드 중 일부만 사용하므로 생성자로 Entity를 받아 필드에 값을 넣는다.

 

3. PostsUpdateRequestDto

@Getter
@NoArgsConstructor
public class PostsUpdateRequestDto {
    private String title;
    private String content;

    @Builder
    public PostsUpdateRequestDto(String title, String content){
        this.title = title;
        this.content = content;
    }
}

 

4. Posts

    public void update(String title, String content){
        this.title = title;
        this.content = content;
    }

 

5. PostsService

@Transactional
public Long update(Long id, PostsUpdateRequestDto requestDto){
    Posts posts = postsRepository.findById(id)
            .orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id=" +id));

    posts.update(requestDto.getTitle(),requestDto.getContent());

    return id;
}

public PostsResponseDto findById(Long id){
    Posts entity = postsRepository.findById(id)
            .orElseThrow(()->new IllegalArgumentException("해당 게시글이 없습니다. id="+id));

    return new PostsResponseDto(entity);
}

update 기능에서 DB에 쿼리를 날리는 부분이 없다. → 더티 체킹(dirty checking)

아래 블로그를 참고하면 좋다.

https://jojoldu.tistory.com/415

 

더티 체킹 (Dirty Checking)이란?

Spring Data Jpa와 같은 ORM 구현체를 사용하다보면 더티 체킹이란 단어를 종종 듣게 됩니다. 더티 체킹이란 단어를 처음 듣는분들을 몇번 만나게 되어 이번 시간엔 더티 체킹이 무엇인지 알아보겠습

jojoldu.tistory.com


참고 도서

https://book.naver.com/bookdb/book_detail.nhn?bid=15871738 

 

스프링 부트와 AWS로 혼자 구현하는 웹 서비스

가장 빠르고 쉽게 웹 서비스의 모든 과정을 경험한다.경험이 실력이 되는 순간!이 책은 제목 그대로 스프링 부트와 AWS로 웹 서비스를 구현합니다. JPA와 JUNIT 테스트, 그레이들, 머스테치, 스프링

book.naver.com

 

728x90
반응형

'개발 > Spring' 카테고리의 다른 글

[Spring] Dispatcher Servlet이란? 개념과 동작 과정  (0) 2024.08.16
[Spring Boot] 예외 처리 전략 - @ControllerAdvice를 이용한 Exception 처리  (0) 2022.09.01
[Spring Boot] 도메인 계층에서 비즈니스 로직 처리  (0) 2022.07.05
[Spring Boot] Spring Boot + Gradle 프로젝트에 JPA 적용  (0) 2022.07.04
[SpringBoot] 테스트 코드 작성, TDD  (0) 2022.05.17
    '개발/Spring' 카테고리의 다른 글
    • [Spring] Dispatcher Servlet이란? 개념과 동작 과정
    • [Spring Boot] 예외 처리 전략 - @ControllerAdvice를 이용한 Exception 처리
    • [Spring Boot] 도메인 계층에서 비즈니스 로직 처리
    • [Spring Boot] Spring Boot + Gradle 프로젝트에 JPA 적용
    goblin
    goblin

    티스토리툴바