Skip to content
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

[5기 김남규, 박유진] Spring Boot JPA 게시판 구현 미션 제출합니다. #269

Open
wants to merge 41 commits into
base: eugene_namgyu
Choose a base branch
from

Conversation

eugene225
Copy link

@eugene225 eugene225 commented Nov 23, 2023

📌 과제 설명

Spring Boot JPA - Rest API를 강의를 듣고, 게시판 구현 미션 수행

👩‍💻 요구 사항과 구현 내용

SpringDataJPA 를 설정한다.

  • datasource : h2

엔티티를 구성한다

  • 회원(User)

    • id (PK) (auto increment)
    • name
    • age
    • hobby
    • created_at
  • 게시글(Post)

    • id (PK) (auto increment)
    • title
    • content
    • created_at
  • 회원과 게시글에 대한 연관관계를 설정한다.

    • 회원과 게시글은 1:N 관계이다.
  • 게시글 Repository를 구현한다. (PostRepository)

API를 구현한다.

  • 페이징 조회 (GET "/posts") : getAll
  • 단건 조회 (GET "/posts/{id}") : findById
  • 게시글 작성 (POST "/posts") : create
  • 게시글 수정 (POST "/posts/{id}") : update

문서화

  • REST-DOCS를 이용해서 문서화한다.

✅ 피드백 반영사항

  • 필드값에 대한 validation 코드 작성
  • PUT vs PATCH → PatchMapping 변경 : update 값이 null로 들어오는 경우 방지
  • DTO 세분화
  • EntityNotFoundException → 커스텀 예외 작성
  • @AllArgsConstructor@RequiredConstructor 수정
  • ApiResponse 커스텀 → ResponseEntity 사용
  • @JsonFormat @DateTimeFormat 포맷 사용 구분
  • 테스트에 yml 설정
  • MappedSuperclass → abstract class 수정
  • page 정보 필요한 것들만 내보내도록 수정

✅ PR 포인트 & 궁금한 점

GeneratedValue 전략 : Sequence vs Identity

  • sequence (H2 ... )
    • sequence object 를 통해서 id 값 부여 → unique 값을 생성
  • DB에 들어가기 전에 id 값이 발급되기 때문에 쓰기 지연이 가능
    • identity (MySQL ... )
    • 데이터베이스 안에 insert 된 후 id 값이 부여 → 쓰기 지연 불가능

CascadeType.ALL + orphanRemoval=true

  • 부모 엔티티를 통해서 자식 엔티티의 생명주기를 관리
  • cascadeType.ALL : persist + remove -> 단순하게 연관관계를 끊었을 경우 고아객체가 된 자식 엔티티가 삭제되지 않아서 발생할 수 있는 문제를 orpahnRemoval=true 옵션을 통해 해결

Entity생성 시 기본 생성자를 필요로 하는 이유

  • JPA의 지연로딩에 사용되는 Proxy 객체를 생성할 때에 Reflection API 가 활용
  • Reflection API : 객체 추정을 위해서는 기본생성자를 필요로 한다.
  • Proxy 객체를 기본 생성하려면 기본 생성자를 필요로 한다.

궁금한 점

  • restdocs 사용 시, page 정보 필요한 것들만 내보내도록 수정하는 방법이 swagger로 변경을 해야만 해결이 되는건지 궁금합니다.

Copy link

@SangHyunGil SangHyunGil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구현하고 반영해주시느라 고생많으셨어요.
따로 코멘트가 없어서 완료된걸로 이해했어요. 다음부터는 완료되면 따로 코멘트 남겨주시면 좋을 것 같아요.
리뷰 남겨놓은 부분은 고민해보시고 남겨주시면 좋을 것 같고 머지해주셔도 좋습니다 👍

@@ -38,8 +38,7 @@ public ApiResponse<PostDto> create(@RequestBody PostRequestDto postRequestDto, @
} // body에서 전부 받는 방식으로

//수정
// post, put, patch ... HTTP 메서드 - 멱등성
@PostMapping("/{id}")
@PutMapping("/{id}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines 13 to 14
private void validateNull(String input) {
if(input.isEmpty() || input.isBlank()) throw new NullPointerException("NPE");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

검증좋네요 👍
나중에 title / content에서 길이와 같은 개별 검증이 들어갈 수 있을 것 같기도 해서 각각 분리해보는걸 고려해봐도 좋을 것 같아요 👍


@RestControllerAdvice
@RestControllerAdvice(basePackageClasses = PostController.class)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

패키지는 공통 exception이지만 포스트 컨트롤러에 대해서만 적용하신 이유가 있나요?

public ApiResponse<String> notFoundHandler(ChangeSetPersister.NotFoundException e) {
return ApiResponse.fail(NOT_FOUND, e.getMessage());
public ResponseEntity<String> notFoundHandler(ChangeSetPersister.NotFoundException e) {
return ResponseEntity.status(NOT_FOUND).body(e.getMessage());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpStatusCode를 활용하는걸 고려해보세요.

return ApiResponse.fail(INTERNAL_SERVER_ERROR, e.getMessage());
} // 다음 타자 .................
public ResponseEntity<String> internalServerErrorHandler(Exception e) {
return ResponseEntity.status(INTERNAL_SERVER_ERROR).body(e.getMessage());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpStatusCode를 활용하는걸 고려해보세요.

Comment on lines 52 to 53
private void validateAge(int age) {
if(age <= 0 || age >= 200) throw new NullPointerException("NPE");
if(age <= 0 || age >= 200) throw new IllegalArgumentException("나이는 1~199세 사이의 값 이어야 합니다.");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

관련 검증을 Age 자체에 넘길 수 있도록 값객체로 선언할 수 있을 것 같아요.
나중에 고민해보시면 좋을 것 같아요 👍


//페이지 조회 -> get
@GetMapping
public ResponseEntity<Page<PostDto>> getAll(Pageable pageable) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pageable로 받는 부분을 수정해보면 좋을 것 같네요 👍

import com.prgrms.dev.springbootboardjpa.dto.UserDto;
import org.springframework.stereotype.Component;

@Component

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼭 빈으로 등록되어야할까요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants