Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## TODO List

### 게시글(Post)

- <b>게시글 작성 API 구현</b>
- [x] 게시글 작성 서비스 구현

<hr>

- <b>게시글 조회 API 구현</b>
- [x] 게시글 단건 조회 구현
- [x] 게시글 단건 조회 구현 시 댓글 조회
- [x] 페이지 응답 시 Pagination 처리
- [x] 요청 Page Size 가 10/30/50이 아닌 경우 10으로 처리
- [x] 게시글 조회 서비스 구현

<hr>

- <b>게시글 수정 API 구현</b>
- [x] 게시글 수정 서비스 구현

<hr>

- <b>게시글 삭제 API 구현</b>
- [x] 게시글 삭제 서비스 구현

<hr>

### 댓글(Comment)
- <b>댓글 작성 API 구현</b>
- [x] 댓글 작성 서비스 구현

<hr>

- <b>댓글 수정 API 구현</b>
- [x] 댓글 수정 서비스 구현

<hr>

- <b>댓글 삭제 API 구현</b>
- [x] 댓글 삭제 서비스 구현

## 구현 시 어렵거나 이해가 되지 않는 부분
- 구현은 했으나 jpa에 대한 심화된 내용숙지가 더 필요한 것 같습니다.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.postgresql:postgresql'
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/io/sparta/board/BoardApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class BoardApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.sparta.board.comment.controller;

import io.sparta.board.comment.dto.CommentRequestDto;
import io.sparta.board.comment.dto.CommentResponseDto;
import io.sparta.board.comment.dto.CommentUpdateRequestDto;
import io.sparta.board.comment.service.CommentService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

@RestController
@RequiredArgsConstructor
@RequestMapping("/posts/{postId}/comments")
public class CommentController {

private final CommentService commentService;

// 댓글 등록
@PostMapping
public ResponseEntity<CommentResponseDto> createComment(
@PathVariable UUID postId,
@RequestBody CommentRequestDto requestDto) {

CommentResponseDto responseDto = commentService.createComment(postId, requestDto);
return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
}

// 댓글 수정
@PutMapping("/{id}")
public ResponseEntity<CommentResponseDto> updateComment(
@PathVariable UUID postId,
@PathVariable UUID id,
@RequestBody CommentUpdateRequestDto requestDto) {

CommentResponseDto responseDto = commentService.updateComment(postId, id, requestDto);
return ResponseEntity.ok(responseDto);
}

// 댓글 삭제
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteComment(
@PathVariable UUID postId,
@PathVariable UUID id) {
commentService.deleteComment(postId, id);

return ResponseEntity.ok("댓글이 삭제되었습니다.");
}
}
15 changes: 15 additions & 0 deletions src/main/java/io/sparta/board/comment/dto/CommentRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.sparta.board.comment.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CommentRequestDto {

private String title;
private String content;

}
29 changes: 29 additions & 0 deletions src/main/java/io/sparta/board/comment/dto/CommentResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.sparta.board.comment.dto;

import io.sparta.board.comment.model.Comment;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.UUID;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class CommentResponseDto {

private UUID id;
private UUID postId;
private String content;

private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private boolean deleted;

public CommentResponseDto(Comment comment) {
this.id = comment.getId();
this.postId = comment.getPost().getId();
this.content = comment.getContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.sparta.board.comment.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CommentUpdateRequestDto {

private String content;

}
46 changes: 46 additions & 0 deletions src/main/java/io/sparta/board/comment/model/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.sparta.board.comment.model;

import io.sparta.board.comment.dto.CommentRequestDto;
import io.sparta.board.comment.dto.CommentUpdateRequestDto;
import io.sparta.board.common.model.BaseEntity;
import io.sparta.board.post.entity.Post;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.UUID;

@Entity
@Getter
@RequiredArgsConstructor
@Table(name = "p_comment")
public class Comment extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id", nullable = false)
private Post post;

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

@Builder
public Comment(Post post, String content) {
this.post = post;
this.content = content;
}

public Comment(CommentRequestDto requestDto, Post post) {
this.post = post;
this.content = requestDto.getContent();;
}

public void updateComment(CommentUpdateRequestDto requestDto) {
this.content = requestDto.getContent();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.sparta.board.comment.repository;

import io.sparta.board.comment.model.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface CommentRepository extends JpaRepository<Comment, UUID> {

Page<Comment> findByPostIdAndDeletedFalse(UUID postId, Pageable pageable);

Optional<Comment> findByIdAndDeletedFalse(UUID id);

List<Comment> findByPostIdAndDeletedFalse(UUID postId);
}
72 changes: 72 additions & 0 deletions src/main/java/io/sparta/board/comment/service/CommentService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.sparta.board.comment.service;

import io.sparta.board.comment.dto.CommentRequestDto;
import io.sparta.board.comment.dto.CommentResponseDto;
import io.sparta.board.comment.dto.CommentUpdateRequestDto;
import io.sparta.board.comment.model.Comment;
import io.sparta.board.post.entity.Post;
import io.sparta.board.comment.repository.CommentRepository;
import io.sparta.board.post.repository.PostRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@Service
@RequiredArgsConstructor
public class CommentService {

private final CommentRepository commentRepository;
private final PostRepository postRepository;

// 댓글 등록
public CommentResponseDto createComment(UUID postId, CommentRequestDto requestDto) {

Post post = postRepository.findByIdAndDeletedFalse(postId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다."));

Comment comment = new Comment(requestDto, post);
Comment savedComment = commentRepository.save(comment);

return new CommentResponseDto(savedComment);
}

// 댓글 수정
@Transactional
public CommentResponseDto updateComment(UUID postId, UUID id, CommentUpdateRequestDto requestDto) {

Post post = postRepository.findByIdAndDeletedFalse(postId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다."));

Comment comment = commentRepository.findByIdAndDeletedFalse(id)
.orElseThrow(() -> new RuntimeException("댓글을 찾을 수 없습니다."));

if (!comment.getPost().getId().equals(postId)) {
throw new RuntimeException("해당 게시글의 댓글이 아닙니다.");
}

comment.updateComment(requestDto);

return new CommentResponseDto(comment);
}

// 댓글 삭제
@Transactional
public CommentResponseDto deleteComment(UUID postId, UUID id) {

Post post = postRepository.findByIdAndDeletedFalse(postId)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다."));

Comment comment = commentRepository.findByIdAndDeletedFalse(id)
.orElseThrow(() -> new RuntimeException("댓글을 찾을 수 없습니다."));

if (!comment.getPost().getId().equals(postId)) {
throw new RuntimeException("해당 게시글의 댓글이 아닙니다.");
}

comment.delete();

return new CommentResponseDto(comment);
}
}
32 changes: 32 additions & 0 deletions src/main/java/io/sparta/board/common/model/BaseEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.sparta.board.common.model;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

@CreatedDate
@Column(name = "created_at")
private LocalDateTime createdAt;

@LastModifiedDate
@Column(name = "updated_at")
private LocalDateTime updatedAt;

@Column(nullable = false)
private boolean deleted;

public void delete() {
this.deleted = true;
}
}
Loading