-
Notifications
You must be signed in to change notification settings - Fork 203
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 게시판 구현 미션 제출합니다. #267
base: main
Are you sure you want to change the base?
Changes from 1 commit
596aff2
6236623
e40522f
7be8ff8
b20a1bd
4a0b783
e7fd8f7
afaec39
61229e9
f1d8044
46d55c3
d9ee9dc
0a53b2d
f991580
28239ca
eac9231
7dc1afe
3e5e984
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,25 @@ | ||
package kdt.jpa.board.global.entity; | ||
|
||
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; | ||
|
||
@EntityListeners(AuditingEntityListener.class) | ||
@MappedSuperclass | ||
@Getter | ||
public class BaseEntity { | ||
|
||
@CreatedDate | ||
@Column(columnDefinition = "TIMESTAMP") | ||
protected LocalDateTime createdDate; | ||
|
||
@LastModifiedDate | ||
@Column(columnDefinition = "TIMESTAMP") | ||
private LocalDateTime updatedDate; | ||
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. 질문) 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. 왜 이렇게 선언돼있는지 모르겠네요 .. 실수한 것 같아요 수정하겠습니다! 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. 질문) 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. 솔직히 특별한 이유 없고, 자바에선 항상 LocalDateTime 만 사용해와서 사용했습니다 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. 지나가다가 발견해서 코멘트 남깁니다. 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.
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. 넵 정확한 네이밍 으로 수정하겠습니다! 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. 요구사항은 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. 넵 빠트린 created_by 필드도 추가해야겠습니다
Comment on lines
+23
to
+24
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. 개인적으로 모든 엔티티 필드에 컬럼 애너테이션을 달고 컬럼 이름을 명시하는 것을 선호해요 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,14 @@ | ||
package kdt.jpa.board.global.exception; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
|
||
@RestControllerAdvice | ||
public class BoardApiExceptionHandler { | ||
|
||
@ExceptionHandler(BoardException.class) | ||
public ResponseEntity<ErrorResponse> handleCustomException(BoardException e) { | ||
return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage())); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package kdt.jpa.board.global.exception; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public class BoardException extends RuntimeException { | ||
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.
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.
|
||
|
||
private final String message; | ||
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. 질문) 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,6 @@ | ||
package kdt.jpa.board.global.exception; | ||
|
||
public record ErrorResponse( | ||
String message | ||
) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package kdt.jpa.board.post.controller; | ||
|
||
import kdt.jpa.board.post.service.PostService; | ||
import kdt.jpa.board.post.service.dto.request.CreatePostRequest; | ||
import kdt.jpa.board.post.service.dto.request.EditPostRequest; | ||
import kdt.jpa.board.post.service.dto.response.PostListResponse; | ||
import kdt.jpa.board.post.service.dto.response.PostResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.web.PageableDefault; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/posts") | ||
public class PostController { | ||
|
||
private final PostService postService; | ||
|
||
@PostMapping | ||
public ResponseEntity<Long> savePost(@RequestBody CreatePostRequest request) { | ||
Long postId = postService.createPost(request); | ||
|
||
return ResponseEntity.ok(postId); | ||
Comment on lines
+29
to
+32
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. 응답 값만 보아서는 어떤 값이 리턴이 되는 지 알기 어렵습니다. 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. 이 부분에 대해서 솔직히 id 를 응답할 필요가 없을거같아서 리턴 타입 자체를 불린으로 바꾸려 하는데, 불린에 대한 응답도 한번 객체화하는게 좋을까요? 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. 불린은 괜찬을듯 |
||
} | ||
|
||
@GetMapping("/{id}") | ||
public ResponseEntity<PostResponse> getPost(@PathVariable Long id) { | ||
PostResponse postResponse = postService.getById(id); | ||
|
||
return ResponseEntity.ok(postResponse); | ||
} | ||
|
||
@GetMapping | ||
public ResponseEntity<PostListResponse> getPosts(@PageableDefault Pageable pageable) { | ||
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.
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. 상세한 |
||
PostListResponse postListResponse = postService.getPosts(pageable); | ||
|
||
return ResponseEntity.ok(postListResponse); | ||
} | ||
|
||
@PatchMapping | ||
public ResponseEntity<Boolean> updatePost(@RequestBody EditPostRequest request) { | ||
boolean result = postService.editPost(request); | ||
|
||
return ResponseEntity.ok(result); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package kdt.jpa.board.post.domain; | ||
|
||
import jakarta.persistence.*; | ||
import kdt.jpa.board.global.entity.BaseEntity; | ||
import kdt.jpa.board.user.domain.User; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor | ||
@Table(name = "posts") | ||
public class Post extends BaseEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
private String title; | ||
|
||
private String content; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "user_id") | ||
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. 질문) 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. 제약조건에 대해서 신경쓰지 않았던 것 같습니다.. 더 신경 써보겠습니다 |
||
private User user; | ||
|
||
public Post(String title, String content, User user) { | ||
this.title = title; | ||
this.content = content; | ||
this.user = user; | ||
Comment on lines
+27
to
+30
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 void edit(String title, String contents) { | ||
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. 필드명은 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. 부주의인거같아요 수정하겠습니다 🫡 |
||
this.title = title; | ||
this.content = contents; | ||
} | ||
|
||
public String getUserName() { | ||
return user.getName(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package kdt.jpa.board.post.repository; | ||
|
||
import kdt.jpa.board.post.domain.Post; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface PostRepository extends JpaRepository<Post, Long> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package kdt.jpa.board.post.service; | ||
|
||
import kdt.jpa.board.global.exception.BoardException; | ||
import kdt.jpa.board.post.domain.Post; | ||
import kdt.jpa.board.post.repository.PostRepository; | ||
import kdt.jpa.board.post.service.dto.request.CreatePostRequest; | ||
import kdt.jpa.board.post.service.dto.request.EditPostRequest; | ||
import kdt.jpa.board.post.service.dto.response.PostListResponse; | ||
import kdt.jpa.board.post.service.dto.response.PostResponse; | ||
import kdt.jpa.board.post.service.utils.PostMapper; | ||
import kdt.jpa.board.user.domain.User; | ||
import kdt.jpa.board.user.repository.UserRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class PostService { | ||
|
||
private final PostRepository postRepository; | ||
private final UserRepository userRepository; | ||
|
||
@Transactional | ||
public Long createPost(CreatePostRequest request) { | ||
User user = userRepository.findById(request.userId()) | ||
.orElseThrow(() -> new BoardException("존재하지 않는 회원입니다")); | ||
Post post = new Post(request.title(), request.content(), user); | ||
|
||
return postRepository.save(post).getId(); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public PostResponse getById(long id) { | ||
Post post = postRepository.findById(id) | ||
.orElseThrow(() -> new BoardException("존재하지 않는 포스트입니다")); | ||
return PostMapper.toPostResponse(post); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public PostListResponse getPosts(Pageable pageable) { | ||
Page<Post> pagedPost = postRepository.findAll(pageable); | ||
return PostMapper.toPostListResponse(pagedPost); | ||
} | ||
|
||
@Transactional | ||
public boolean editPost(EditPostRequest request) { | ||
Post post = postRepository.findById(request.postId()) | ||
.orElseThrow(() -> new BoardException("존재하지 않는 포스트입니다")); | ||
|
||
post.edit(request.title(), request.content()); | ||
return true; | ||
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,8 @@ | ||
package kdt.jpa.board.post.service.dto.request; | ||
|
||
public record CreatePostRequest( | ||
String title, | ||
String content, | ||
long userId | ||
) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package kdt.jpa.board.post.service.dto.request; | ||
|
||
public record EditPostRequest ( | ||
long postId, | ||
String title, | ||
String content | ||
) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package kdt.jpa.board.post.service.dto.response; | ||
|
||
import org.springframework.data.domain.Page; | ||
|
||
public record PostListResponse( | ||
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. 반환은 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. 페이지 안에 콘텐츠 자체는 List 라 이런식으로 네이밍을 했는데, 이런 경우는 Page 라고 명시를 해주는게 좋을까요? |
||
Page<PostResponse> responses | ||
) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package kdt.jpa.board.post.service.dto.response; | ||
|
||
public record PostResponse ( | ||
String title, | ||
String content, | ||
String userName | ||
) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package kdt.jpa.board.post.service.utils; | ||
|
||
import kdt.jpa.board.post.domain.Post; | ||
import kdt.jpa.board.post.service.dto.response.PostListResponse; | ||
import kdt.jpa.board.post.service.dto.response.PostResponse; | ||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
import org.springframework.data.domain.Page; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public final class PostMapper { | ||
|
||
public static PostResponse toPostResponse(Post post) { | ||
return new PostResponse(post.getTitle(), post.getContent(), post.getUserName()); | ||
} | ||
|
||
public static PostListResponse toPostListResponse(Page<Post> posts) { | ||
Page<PostResponse> responses = posts.map(PostMapper::toPostResponse); | ||
return new PostListResponse(responses); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package kdt.jpa.board.user.domain; | ||
|
||
import jakarta.persistence.*; | ||
import kdt.jpa.board.global.entity.BaseEntity; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor | ||
@Table(name = "users") | ||
public class User extends BaseEntity { | ||
Comment on lines
+11
to
+12
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. 테이블 이름을 복수형으로 선언하신 이유가 있을까요??? 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. user 가 mysql 에서 이미 사용중인 네이밍이라 테이블 이름으로 사용이 안되는거로 알고있어서 복수형으로 선언했습니다! 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. 아하 이미 사용중인 네임이였군여, 어쩐지 대부분 MEMBER, ACCOUNT 이런식으로 테이블 이름을 사용하더라고요 ㅎㅎㅎ |
||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
private String name; | ||
|
||
private int age; | ||
|
||
private String hobby; | ||
|
||
public User(String name, int age, String hobby) { | ||
this.name = name; | ||
this.age = age; | ||
this.hobby = hobby; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package kdt.jpa.board.user.repository; | ||
|
||
import kdt.jpa.board.user.domain.User; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface UserRepository extends JpaRepository<User, Long> { | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
spring: | ||
datasource: | ||
driver-class-name: com.mysql.cj.jdbc.Driver | ||
url: jdbc:mysql://127.0.0.1:3306/jpa_board?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul | ||
username: root | ||
password: 110811!! | ||
jpa: | ||
open-in-view: false | ||
hibernate: | ||
ddl-auto: create | ||
show-sql: true | ||
properties: | ||
hibernate.format_sql: true | ||
server: | ||
servlet: | ||
encoding: | ||
charset: UTF-8 | ||
enabled: true | ||
force: true |
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.
인스턴스화하지 않을 객체이니 추상클래스로 변경해보는 것은 어때요 ??
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.
앗 맞는말인거같아요! 수정하겠습니다