-
Notifications
You must be signed in to change notification settings - Fork 10
과제 1-1 jeongjongyun 과제제출 #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request.ArticlesPatchRequestDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request.ArticlesRequestDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.response.ArticlesResponseDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.entity.ArticlesEntity; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.repository.Articlesrepository; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.service.ArticlesService; | ||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/articles") | ||
| @RequiredArgsConstructor | ||
| public class ArticlesController { | ||
| private final ArticlesService articlesService; | ||
| private final Articlesrepository articlesrepository; | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<List<ArticlesResponseDto>> getAriticles() { | ||
| List<ArticlesResponseDto> articles = articlesService.getAll(); | ||
| return ResponseEntity.ok(articles); | ||
| } | ||
| @GetMapping("/{id}") | ||
| public ResponseEntity<ArticlesResponseDto> getArticles(@PathVariable Long id) { | ||
| if(!articlesService.existsById(id)) { | ||
| return ResponseEntity.notFound().build(); | ||
| } | ||
| ArticlesResponseDto articles = articlesService.getOne(id); | ||
| return ResponseEntity.ok(articles); | ||
| } | ||
| @PostMapping | ||
| public ResponseEntity<ArticlesResponseDto> createArticles(@Valid @RequestBody ArticlesRequestDto articles) { | ||
| if (!articlesService.checkRequest(articles)) | ||
| //유효성 검사에 실패 했을때 (checkRequest) | ||
| return ResponseEntity.badRequest().build(); | ||
| ArticlesResponseDto article = articlesService.saveArticle(articles); | ||
| if (article == null) {// DB에 저장이 실패할때 | ||
| return ResponseEntity.internalServerError().build(); | ||
| } | ||
| return ResponseEntity.status(201).body(article); | ||
| } | ||
| @PatchMapping("/{id}") | ||
| public ResponseEntity<ArticlesResponseDto> update( | ||
| @PathVariable Long id, @Valid @RequestBody ArticlesPatchRequestDto request) { | ||
| if(!articlesService.existsById(id)) { | ||
| return ResponseEntity.notFound().build(); | ||
| } | ||
|
|
||
| if(!articlesService.hasValidPatchData(request)) { | ||
| return ResponseEntity.badRequest().build(); | ||
| } | ||
| ArticlesResponseDto update = articlesService.updateArticle(id, request); | ||
| return ResponseEntity.ok(update); | ||
| } | ||
|
|
||
|
|
||
| @DeleteMapping("/{id}") | ||
| public ResponseEntity<Void> deleteArticles(@PathVariable Long id) { | ||
| if(!articlesService.existsById(id)){ | ||
| return ResponseEntity.notFound().build(); | ||
| } | ||
| articlesService.deleteById(id); | ||
| return ResponseEntity.noContent().build(); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| } | ||
|
Comment on lines
+15
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이런 유효성 검사,존재 확인 및 레포지터리(영속계층) 사용은 비즈니스로직에 해당하는 것 같습니다.책임분리에 대해 고민해보시고 이러한 로직은 서비스로 옮기는게 좋을 것 같습니다 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request; | ||
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| public class ArticlesPatchRequestDto { | ||
| @NotBlank(message = "제목은 비어 있을 수 없습니다.") | ||
| private String title; | ||
| @NotBlank(message = "내용은 비어 있을 수 없습니다.") | ||
| private String content; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request; | ||
| import lombok.AllArgsConstructor; | ||
|
|
||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import jakarta.validation.constraints.NotBlank; | ||
|
|
||
| @Getter | ||
| @AllArgsConstructor | ||
| @NoArgsConstructor | ||
| public class ArticlesRequestDto { | ||
| @NotBlank(message = "제목은 비어 있을 수 없습니다.") | ||
| private String title; | ||
| @NotBlank(message = "내용은 비어 있을 수 없습니다.") | ||
| private String content; | ||
|
|
||
|
|
||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request; | ||
|
|
||
| public @interface NotBlank { | ||
| String message(); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 어노테이션을 정의하신 이유가 무엇인가요?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 @notblank 어노테이션을 쓰다가 인텔리제이에서 자동으로 추가해준 것을 못 보고 넣은거 같습니다.. 수정하겠습니다 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.response; | ||
|
|
||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| public class ArticlesResponseDto { | ||
| private String title; | ||
| private String content; | ||
|
|
||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.entity; | ||
|
|
||
| import com.gsm._8th.class4.backed.task._1._1.global.entity.BaseIdxEntity; | ||
| import jakarta.persistence.Column; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.Table; | ||
| import lombok.Getter; | ||
|
|
||
| @Entity | ||
| @Table(name = "task.1-1") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 테이블 명으로 이러한 명칭은 적절하지 않을 것 같습니다. |
||
| @Getter | ||
| public class ArticlesEntity extends BaseIdxEntity { | ||
| @Column(nullable = false) | ||
| private String title; | ||
|
|
||
| @Column(nullable = false , columnDefinition = "TEXT") | ||
| private String content; | ||
| public ArticlesEntity() {} | ||
| public ArticlesEntity( String title, String content) { | ||
| this.title = title; | ||
| this.content = content; | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생성자를 직접 정의하기 보단 Lombok에서 제공하는 생성자 생성 어노테이션들을 적용해주세요 |
||
| public void update(String title, String content) { | ||
| if(title != null) | ||
| { | ||
| this.title = title; | ||
| } | ||
| if(content != null){ | ||
| this.content = content; | ||
| } | ||
| } | ||
|
Comment on lines
+24
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update 메서드에서 이러한 null 검사를 하기보단 애초에 서비스 로직에서 null검사를 하는것이 더 깔끔하지 않을까요? |
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.repository; | ||
|
|
||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.entity.ArticlesEntity; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| public interface Articlesrepository extends JpaRepository<ArticlesEntity, Long> { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.service; | ||
|
|
||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request.ArticlesPatchRequestDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request.ArticlesRequestDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.response.ArticlesResponseDto; | ||
| import jakarta.validation.Valid; | ||
| import org.springframework.stereotype.Service; | ||
| import java.util.List; | ||
| @Service | ||
| public interface ArticlesService { | ||
| // 게시글 모든 글 조회 | ||
| List<ArticlesResponseDto> getAll(); | ||
| //단일 게시글 조회 | ||
| ArticlesResponseDto getOne(Long id); | ||
| //게시글 생성 | ||
| ArticlesResponseDto saveArticle(ArticlesRequestDto request); | ||
| //게시글 수정 | ||
| ArticlesResponseDto updateArticle(Long id, @Valid ArticlesPatchRequestDto request); | ||
| //게시글 삭제 | ||
| boolean deleteById(Long id); | ||
| //게시글 존재 여부 확인 | ||
| boolean existsById(Long id); | ||
| //수정 요청 데이터 확인 | ||
| boolean hasValidPatchData(@Valid ArticlesPatchRequestDto request); | ||
| //유효성 검사 | ||
| boolean checkRequest(@Valid ArticlesRequestDto request); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| package com.gsm._8th.class4.backed.task._1._1.domain.ariticle.service; | ||
|
|
||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request.ArticlesPatchRequestDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.request.ArticlesRequestDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.controller.response.ArticlesResponseDto; | ||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.entity.ArticlesEntity; | ||
|
|
||
| import com.gsm._8th.class4.backed.task._1._1.domain.ariticle.repository.Articlesrepository; | ||
| import com.gsm._8th.class4.backed.task._1._1.global.entity.BaseIdxEntity; | ||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| @Transactional(readOnly = true) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 각 메서드에 트랜젝션을 별도로 선언하거나 하였다면 클래스단에서 선언하기 보단 메서드마다 알맞게 선언해주는게 좋을 것 같습니다 |
||
| public class ArticlesServiceImpl implements ArticlesService { | ||
|
|
||
| private final Articlesrepository articlesrepository; | ||
| @Override | ||
| public List<ArticlesResponseDto> getAll(){ | ||
| List<ArticlesEntity> entities = articlesrepository.findAll(); | ||
| List<ArticlesResponseDto> dtos = entities.stream() | ||
| .map(entity -> convertToResponseDto(entity)) | ||
| .collect(Collectors.toList()); | ||
| Collections.reverse(dtos); | ||
| return dtos; | ||
|
|
||
|
|
||
| } | ||
| @Override | ||
| public ArticlesResponseDto getOne(Long id) { | ||
| Optional<ArticlesEntity> result = articlesrepository.findById(id); | ||
|
|
||
| if(result.isPresent()){ | ||
| ArticlesEntity entity = result.get(); | ||
| return convertToResponseDto(entity); | ||
| } | ||
| else { | ||
| return null; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| @Transactional | ||
| public ArticlesResponseDto saveArticle(ArticlesRequestDto request) { | ||
| ArticlesEntity entity = new ArticlesEntity(request.getTitle(), request.getContent()); | ||
| ArticlesEntity savedEntity = articlesrepository.save(entity); | ||
| return convertToResponseDto(savedEntity); | ||
| } | ||
|
|
||
| @Override | ||
| @Transactional | ||
| public ArticlesResponseDto updateArticle(Long id, ArticlesPatchRequestDto request) { | ||
| Optional<ArticlesEntity> updateresult = articlesrepository.findById(id); | ||
|
|
||
| if(updateresult.isEmpty()) { // 없으면 null 반환 | ||
| return null; | ||
| } | ||
|
|
||
| ArticlesEntity entity = updateresult.get(); // 있을 때만 .get() 호출 | ||
| entity.update(request.getTitle(), request.getContent()); | ||
| ArticlesEntity savedEntity = articlesrepository.save(entity); | ||
| return convertToResponseDto(savedEntity); | ||
| } | ||
|
|
||
| @Override | ||
| @Transactional | ||
| public boolean deleteById(Long id) { | ||
| if(!articlesrepository.existsById(id)){ | ||
| return false; | ||
| } | ||
| articlesrepository.deleteById(id); | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean existsById(Long id) { | ||
|
|
||
| return articlesrepository.existsById(id); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean hasValidPatchData(ArticlesPatchRequestDto request) { | ||
| return existsTitle(request) || existsContent(request); | ||
| } | ||
|
|
||
| private boolean existsTitle(ArticlesPatchRequestDto request) { // 타입 변경 | ||
| return request.getTitle() != null; | ||
| } | ||
|
|
||
| private boolean existsContent(ArticlesPatchRequestDto request) { // 타입 변경 | ||
| return request.getContent() != null; | ||
| } | ||
| private ArticlesResponseDto convertToResponseDto(ArticlesEntity entity) { | ||
| return ArticlesResponseDto.builder() | ||
| .title(entity.getTitle()) | ||
| .content(entity.getContent()) | ||
| .build(); | ||
| } | ||
| @Override | ||
| public boolean checkRequest(ArticlesRequestDto request) { | ||
| // title과 content가 모두 null이 아니고 비어있지 않은지 확인 | ||
| return request.getTitle() != null && !request.getTitle().trim().isEmpty() && | ||
| request.getContent() != null && !request.getContent().trim().isEmpty(); | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
각 메서드 사이에 개행해주세요