[Spring] 게시판 만들기 - JPA

koline·2024년 7월 9일
0

Spring

목록 보기
13/15

지난 포스팅에 생성한 스프링 부트 애플리케이션에 게시판을 생성해보자




패키지 구조





소스코드


  • BaseResponse.java
@AllArgsConstructor
@Getter
public class BaseResponse {

    @JsonProperty("isSuccess")
    boolean isSuccess;

    String message;

    Object data;
}
  • PostController.java
@RestController
@RequiredArgsConstructor
@RequestMapping("/post")
public class PostController {

    private final PostService postService;

    @GetMapping("/list")
    @ResponseStatus(HttpStatus.OK)
    public ResponseEntity<BaseResponse> getPostList(
            Pageable pageable
    ) {
        return ResponseEntity.ok(new BaseResponse(true, "", postService.getPostList(pageable)));
    }

    @PostMapping
    public ResponseEntity<BaseResponse> createPost(
            @RequestBody PostDto post
    ) {
        if (post.getTitle() == null || post.getTitle().isBlank()) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "제목은 필수입력 항목입니다.", null));
        }
        
        if (post.getContent() == null || post.getContent().isBlank()) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "내용은 필수입력 항목입니다.", null));
        }

        return ResponseEntity.ok(new BaseResponse(true, "", postService.createPost(post)));
    }

    @GetMapping("/{id}")
    public ResponseEntity<BaseResponse> getPostById(
            @PathVariable(name = "id") String id
    ) {
        PostDto post = postService.getPostById(Long.valueOf(id));

        if (post == null) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "유효하지 않은 id입니다.", null));
        }

        return ResponseEntity.ok(new BaseResponse(true, "", post));
    }

    @PatchMapping
    public ResponseEntity<BaseResponse> updatePost(
            @RequestBody PostDto post
    ) {
        if (post.getId() == null || post.getId() < 0) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "유효하지 않은 id입니다.", null));
        }
        
        if (post.getTitle() == null || post.getTitle().isBlank()) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "제목은 필수입력 항목입니다.", null));
        }
        
        if (post.getContent() == null || post.getContent().isBlank()) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "내용은 필수입력 항목입니다.", null));
        }

        PostDto target = postService.getPostById(post.getId());

        if (target == null) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "유효하지 않은 게시물입니다.", null));
        }

        PostDto updatedPost = postService.updatePost(post);

        return ResponseEntity.ok(new BaseResponse(true, "", updatedPost));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<BaseResponse> deletePost(
            @PathVariable(name = "id") String id
    ) {
        PostDto post = postService.getPostById(Long.valueOf(id));

        if (post == null) {
            return ResponseEntity.badRequest().body(new BaseResponse(false, "유효하지 않은 id입니다.", null));
        }

        postService.deletePost(Long.valueOf(id));

        Map<String, String> result = Map.of("deletedPost", id);

        return ResponseEntity.ok(new BaseResponse(true, "", result));
    }
}
  • PostService.java
public interface PostService {

    List<PostDto> getPostList(Pageable pageable);

    PostDto createPost(PostDto post);

    PostDto getPostById(Long id);

    PostDto updatePost(PostDto post);

    void deletePost(Long id);
}
  • PostServiceImpl.java

@Service
@RequiredArgsConstructor
@Transactional
public class PostServiceImpl implements PostService {

    private final PostRepository postRepository;

    @Override
    public List<PostDto> getPostList(Pageable pageable) {
        return postRepository.findAll(pageable).stream().map(PostEntity::toDto).toList();
    }

    @Override
    public PostDto createPost(PostDto post) {
        return postRepository.save(post.toEntity()).toDto();
    }

    @Override
    public PostDto getPostById(Long id) {
        return postRepository.findById(id).map(PostEntity::toDto).orElse(null);
    }

    @Override
    public PostDto updatePost(PostDto post) {
        return postRepository.save(post.toEntity()).toDto();
    }

    @Override
    public void deletePost(Long id) {
        postRepository.deleteById(id);
    }
}
  • PostRepository.java
public interface PostRepository extends JpaRepository<PostEntity, Long> {
}
  • PostEntity.java
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table
public class PostEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false, updatable = false)
    private Long id;

    @Column(name = "title", nullable = false, length = 100)
    private String title;

    @Column(name = "content", nullable = false, columnDefinition = "TEXT")
    private String content;

    @Column(name = "created_at", nullable = false, updatable = false)
    @CreatedDate
    private LocalDateTime createdAt;

    @Builder.Default
    @Column(name = "updated_at")
    @LastModifiedDate
    private LocalDateTime updatedAt = null;

    @PrePersist
    public void prePersist() {
        this.createdAt = LocalDateTime.now();
    }

    @PreUpdate
    public void preUpdate() {
        this.updatedAt = LocalDateTime.now();
    }


    public PostDto toDto() {
        return PostDto.builder()
                .id(id)
                .title(title)
                .content(content)
                .createdAt(createdAt)
                .updatedAt(updatedAt)
                .build();
    }

}
  • PostDto.java
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostDto {

    private Long id;

    private String title;

    private String content;

    private LocalDateTime createdAt;

    private LocalDateTime updatedAt;

    public PostEntity toEntity() {
        return PostEntity.builder()
                .id(id)
                .title(title)
                .content(content)
                .createdAt(createdAt)
                .updatedAt(updatedAt)
                .build();
    }
}

마지막으로 application.properties에 아래 코드를 추가한다.

... 생략
spring.jpa.hibernate.ddl-auto=create

위 코드를 추가하면 @Entity 어노테이션이 붙은 클래스와 대칭되는 테이블을 데이터베이스에 자동 생성해준다.




테스트


  • POST 요청

  • GET 요청 (단건)

  • GET 요청 (다건)

  • PATCH 요청

  • DELETE 요청

모든 요청에 정상 응답이 반환 된다.

이번엔 에러 처리가 정상적으로 이뤄 지는지 확인해보자.

  • 없는 id로 GET 요청

  • title 없이 POST 요청

  • content 없이 POST 요청

  • 없는 id로 PATCH 요청

  • title 없이 PATCH 요청

  • content 없이 PATCH 요청

  • 없는 id로 DELETE 요청

에러 처리가 정상적으로 이뤄졌다.

profile
개발공부를해보자

0개의 댓글

관련 채용 정보