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

Post crud task #41

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
38b2bac
feat: PostCRUD
chanmin97 Apr 4, 2024
e764e2e
refactor: fix testcode
chanmin97 Apr 7, 2024
ef5c233
merge
chanmin97 Apr 7, 2024
a020322
feat: PostController updatePost
chanmin97 Apr 7, 2024
ead0646
feat: PostService updatePost
chanmin97 Apr 7, 2024
8d2f19d
Test: updatePost
chanmin97 Apr 7, 2024
754fe55
:sparkles: [Add] GlobalExceptionHandler 추가
chanmin97 Apr 10, 2024
f14c0d3
:white_check_mark: [Test] PostServiceTest 추가
chanmin97 Apr 10, 2024
2e75a22
:white_check_mark: [Test] PostControllerTest 수정
chanmin97 Apr 10, 2024
f5ef79b
:recycle: Refactor: Post
chanmin97 Apr 15, 2024
585be82
:recycle: Refactor: PostReply
chanmin97 Apr 15, 2024
f90269d
:sparkles: Add: PostResponse
chanmin97 Apr 15, 2024
d6efc0f
:sparkles: Add: AddPostRequest
chanmin97 Apr 15, 2024
fce47ee
:sparkles: Add: UpdatePostRequest
chanmin97 Apr 15, 2024
2253c2a
:sparkles: Add: PostService
chanmin97 Apr 15, 2024
681cee9
:sparkles: Add: PostController
chanmin97 Apr 15, 2024
5a97f47
:sparkles: Add: Post
chanmin97 Apr 15, 2024
f5f5f80
:sparkles: Add: PostApiControllerTest
chanmin97 Apr 15, 2024
9e1da2e
:sparkles: Add: PostApiController
chanmin97 Apr 15, 2024
056b3b7
:sparkles: Add: PostApiControllerTest
chanmin97 Apr 15, 2024
9dac3a8
:sparkles: Add: PostReply
chanmin97 Apr 15, 2024
47d0df2
:sparkles: Add: PostRepository
chanmin97 Apr 15, 2024
aaf1eaf
:sparkles: Add: PostServiceTest.java
chanmin97 Apr 15, 2024
1cfe8cf
:fire: Delete : PostServiceTest
chanmin97 Apr 16, 2024
35f76a8
:fire: Delete: PostControllerTest
chanmin97 Apr 16, 2024
7d30459
:fire: Delete: User
chanmin97 Apr 16, 2024
c159778
:twisted_rightwards_arrows: Merge Main
chanmin97 Apr 16, 2024
a296d96
:twisted_rightwards_arrows: Merge Main
chanmin97 Apr 16, 2024
f8f28c5
:white_check_mark: Test: PostApiControllerTest
chanmin97 Apr 16, 2024
c416a97
:white_check_mark: Test: PostApiControllerTest생성예외
chanmin97 Apr 22, 2024
56843fb
:sparkles: Feat : 로깅 및 Post컨트롤러 태그 추가
chanmin97 May 4, 2024
90bf54b
:sparkles: Feat : 페이징 기능 구현
chanmin97 May 4, 2024
cba91dd
:white_check_mark: Test : 페이징 기능 테스트코드 추가
chanmin97 May 4, 2024
9def7a0
Comment: 서비스코드 주석추가
chanmin97 May 8, 2024
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
1 change: 1 addition & 0 deletions spring-boot-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ dependencies {
runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'
// for lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.ssafy.springbootapi.domain.post.api;

import com.ssafy.springbootapi.domain.post.application.PostService;
import com.ssafy.springbootapi.domain.post.domain.Post;
import com.ssafy.springbootapi.domain.post.dto.AddPostRequest;
import com.ssafy.springbootapi.domain.post.dto.PostResponse;
import com.ssafy.springbootapi.domain.post.dto.UpdatePostRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "Post", description = "Post 관련 API 입니다.")
@RequiredArgsConstructor
@RestController
public class PostController {

private final PostService postService;

@Operation(summary = "게시글 등록")
@PostMapping("/api/v1/posts")
public ResponseEntity<Post> addPost(@Validated @RequestBody AddPostRequest request) {
Post savedPost = postService.save(request);

return ResponseEntity.status(HttpStatus.CREATED)
.body(savedPost);
}



/** 스웨거에 넣을때
* {
* "page": 0, //페이지번호
* "size": 3, //한페이지당 몇개 표시할지
* "sort": [
* "id,asc" // id 오름차순
* ]
* }
* @param pageable
* @return
*/
@Operation(summary = "게시글 리스트 불러오기 페이지버전")
@GetMapping("/api/v1/posts")
public ResponseEntity<Page<PostResponse>> findAllPosts(Pageable pageable) {
Page<PostResponse> posts = postService.findAll(pageable);
return ResponseEntity.ok()
.body(posts);
}


@Operation(summary = "게시글 아이디로 조회")
@GetMapping("/api/v1/posts/{id}")
public ResponseEntity<PostResponse> findPost(@PathVariable Long id) {
Post post = postService.findById(id);

return ResponseEntity.ok()
.body(new PostResponse(post));
}

@Operation(summary = "게시글 삭제")
@DeleteMapping("/api/v1/posts/{id}")
public ResponseEntity<Void> deletePost(@PathVariable Long id) {
postService.delete(id);
return ResponseEntity.ok()
.build();
}

@Operation(summary = "게시글 수정")
@PutMapping("/api/v1/posts/{id}")
public ResponseEntity<Post> updatePost(@PathVariable Long id, @RequestBody UpdatePostRequest request) {
Post updatedPost = postService.update(id, request);

return ResponseEntity.ok()
.body(updatedPost);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.ssafy.springbootapi.domain.post.application;

import com.ssafy.springbootapi.domain.post.dao.PostRepository;
import com.ssafy.springbootapi.domain.post.domain.Post;
import com.ssafy.springbootapi.domain.post.dto.AddPostRequest;
import com.ssafy.springbootapi.domain.post.dto.PostResponse;
import com.ssafy.springbootapi.domain.post.dto.UpdatePostRequest;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

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

@RequiredArgsConstructor
@Service
public class PostService {
private final PostRepository postRepository;

/**
* 게시글 등록
* @param request
* @return
*/
public Post save(AddPostRequest request) {
return postRepository.save(request.toEntity());
}

/**
* 게시글 리스트 불러오기
* @return
*/
public List<Post> findAll(){
return postRepository.findAll();
}

/**
* id로 게시글 찾기
* @param id 찾을 게시글 id
* @return
*/
public Post findById(long id) {
return postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not found : " + id));
}


/**
* 게시글 삭제
* @param id 삭제할 게시글 id
*/
public void delete(long id) {
postRepository.deleteById(id);
}

/**
* 게시글 수정
* @param id 수정할 게시글 id
* @param request
* @return
*/
@Transactional
public Post update(long id, UpdatePostRequest request) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not found : " + id));

post.update(request.getTitle(), request.getContent());

return post;
}


/**
* 페이지 나눠서 리스트 불러오기
* @param pageable
* @return
*/
//페이징 기능
public Page<PostResponse> findAll(Pageable pageable) {
Page<Post> posts = postRepository.findAll(pageable);
return posts.map(PostResponse::new); // 여기서 post를 PostReponse객체로 전부 변환
//이렇게 해주면 Post가 외부에 노출되는 것을 방지하고, 필요한 데이터만을 담은 DTO(PostResponse)를 클라이언트에 반환하게됨
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ssafy.springbootapi.domain.post.dao;

import com.ssafy.springbootapi.domain.post.domain.Post;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
Page<Post> findAll(Pageable pageable); //페이징 기능기준
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.ssafy.springbootapi.domain.post.domain;


import com.ssafy.springbootapi.domain.user.domain.User;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.LocalDateTime;

@Builder
@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id;

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

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

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

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

@Builder.Default
@Column(name = "likes")
private Long likes=0L;

@Builder.Default
@Column(name = "dislikes")
private Long dislikes=0L;

@Builder.Default
@Column(name = "views")
private Long views=0L;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.ssafy.springbootapi.domain.post.domain;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.LocalDateTime;

@Entity
@Getter
public class PostReply {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id;

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

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

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

@Column(name = "likes", nullable = false)
private Long likes;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ssafy.springbootapi.domain.post.dto;

import com.ssafy.springbootapi.domain.post.domain.Post;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;


@NoArgsConstructor
@AllArgsConstructor
@Getter
public class AddPostRequest {
@NotEmpty
@NotNull
private String title;

@NotEmpty
@NotNull
private String content;

public Post toEntity() {
return Post.builder()
.title(title)
.content(content)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ssafy.springbootapi.domain.post.dto;

import com.ssafy.springbootapi.domain.post.domain.Post;
import lombok.Getter;

@Getter
public class PostResponse {
private final String title;
private final String content;

public PostResponse(Post post) {
this.title = post.getTitle();
this.content = post.getContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ssafy.springbootapi.domain.post.dto;

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

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class UpdatePostRequest {
private String title;
private String content;
}
9 changes: 8 additions & 1 deletion spring-boot-api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,11 @@ springdoc:
display-query-params-without-oauth2: true
doc-expansion: none
paths-to-match:
- /api/**
- /api/**

logging:
level:
root: INFO
# com:
# ssafy.springbootapi.domain: DEBUG
# ssafy.springbootapi.domain 아래에 있는 것들만 디버그로 보고싶을때 사용
Loading