24/12/30(월)
게시판과 게시글의 관계
게시판과 게시글은 1:N관계이다.
게시판이 없는 게시글은 없다. 따라서 게시글을 생성할때 게시판 id가 있어야만 만들 수 있다.
1. DTO설계
public record PostRequest(
String content,
String title,
String createdAt
) {
}
public record PostResponse(
String title,
String content,
Long id,
String createdAt) {
}
2. API설계 가지고 controller 작성
에러가 나든말든 일단, 작성하고 그 다음 함수들을 service에 생성해준다.
@RestController
public class PostController {
private PostService postService;
public PostController(PostService postService) {
this.postService = postService;
}
//생성
@PostMapping("/posts")
public PostResponse createPost(@RequestBody PostRequest postRequest){
return postService.create(postRequest);
}
//조회
@GetMapping("/posts/{postId}")
public PostResponse getPost(@PathVariable Long postId){
return postService.getPostId(postId);
}
//수정
@PutMapping("/posts/{postId}")
public PostResponse putPost(@PathVariable Long postId, @RequestBody PostRequest postRequest){
return postService.updatePost(postId,postRequest);
}
//삭제
@DeleteMapping("/posts/{postId}")
public void deletePost(@PathVariable Long postId){
postService.deletePost(postId);
}
}
3. controller의 service함수 작성
@Service
public class PostService {
private PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
Respository는 service에서 사용한다. 따라서 Respository를 먼저 만들어준다.
public interface PostRepository extends JpaRepository<Post, Long> {
그리고 Service에서 사용할 Entity도 만들어준다.
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;
private String title;
public Post() {
}
public Post(String content, String title){
this.content = content;
this.title = title;
}
public Long getId() {
return id;
}
public String getContent() {
return content;
}
public String getTitle() {
return title;
}
public void setContent(String content) {
this.content = content;
}
public void setTitle(String title) {
this.title = title;
}
}
❗Entity의 중요한 요소
1. id설정
2. 관계 설정
3. 기본 생성자
4. id값을 뺀 생성자 - Entity속 id값은 노출되어서는 안된다.
5. 전체 getter
5가지를 설정해놓아야 한다.
그리고 Service의 함수를 만들어준다.
//service
public PostResponse create(PostRequest postRequest) {
Post post = postRepository.save(new Post(postRequest.title(), postRequest.content()));
return new PostResponse(post.getTitle(), post.getContent(), post.getId());
}
//조회
public PostResponse getPostId(Long postId) {
Post post = postRepository.findById(postId).orElseThrow();
return new PostResponse(post.getTitle(), post.getContent(), postId);
}
@Transactional
public PostResponse updatePost(Long postId, PostRequest postRequest) {
Post post = postRepository.findById(postId).orElseThrow();
post.setTitle(postRequest.title());
post.setContent(postRequest.content());
return new PostResponse(post.getTitle(), post.getContent(), postId);
}
public void deletePost(Long postId) {
Post post = postRepository.findById(postId).orElseThrow();
postRepository.delete(post);
}
}
Post post = postRepository.findById(postId).orElseThrow();
그리고 수정을 하기 위해선 setter를 써야한다. setter함수는 Entitiy에 들어있다. Entity에서 setter를 설정해 준 후 set함수를 써서 변경해준다.
post.setTitle(postRequest.title());
post.setContent(postRequest.content());
마지막에 반환만 하면 된다.
❗ @Transactional
- 수행되어야 모든 것들을 모아놓은 것이다. 수행할 일들을 모두 처리하지 못 한 경우에는 원 상태로 복구한다. 즉, 작업의 일부만 적용되는 현상이 발생하지 않는다.
- 수정이 제대로 변경되려면
트렌젝션을 붙여야한다.- ex) 송금:
나는 엄마한테 송금을 했는데, 중간에 끊겨버리면 내 돈은 날라가버리고, 엄마는 돈을 못받는 경우가 생긴다. 이런 경우를 방지하기 위해트렌젝션을 붙여준다. 그러면 중간에 끊겼을때 다시 원상태로 돌아가기 떄문에 내 돈이 다시 내 통장으로 돌아오게 된다.
앞서 이야기 했듯이 1:N관계를 맺어야한다.
Entity에서 관계를 맺어주는데, N에 @ManyToOne을 붙여주면된다.
@ManyToOne
//게시글은 하나의 게시판에 온다
private Board board;
원래 Entity는 DB에 칼럼을 정의한다. DB는 String, int 이런 bigint들은 알기 때문에 뭔가를 해주지 않아도 알아서 들어가는데, board는 칼럼이 처음보기 때문에 칼럼에 넣어주지 않는다. 따라서 @를 붙여 이건 칼럼이 아니라, 내가 관계를 매핑한거야~ 라고 알려주는 것이다.
관계를 맺었다.라는 건 boardId가 없으면 게시글 작성이 안된다 라는 것이다.
1. Entity 생성자의 board를 넣어준다.
public Post(String content, String title, String createdAt, Board board){
this.content = content;
this.title = title;
this.createdAt = createdAt;
this.board = board;
}
2. BoardId가 있어야 게시글 작성이 되기 때문에 Requeest에도 boardId가 있어야한다.
public record PostRequest(
String content,
String title,
String createdAt,
Long boardId
) {
}
3. controller수정
@GetMapping("/posts")
public List<PostResponse> getOneBoard(@RequestParam(required = false) Long boardId){
return postService.getContentInTitle(boardId);
}
posts 자체를 조회했을 때 boardId를 RequestParam으로 받고, 그걸 토대로 service도 수정한다.
RequestBodyvsRequestParam
- RequestBody : http body에 있는 내용을 오브젝트로 반환한다.
- RequestParam : URL에 요청 파라미터를 보낸다.
4. Service수정
1. 게시글을 만들 때 무조건 boardId를 받아줘야한다.
public PostResponse create(PostRequest postRequest) {
//board의 id를 저장해야된다.
Board board = boardRepository.findById(postRequest.boardId()).orElseThrow();
Post post = postRepository.save(new Post(postRequest.title(), postRequest.content(), postRequest.createdAt(), board));
return new PostResponse(post.getTitle(), post.getContent(), post.getId(), post.getCreatedAt());
}
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findByBoardId(Long boardId);
}
특정 게시판내의 게시글 만드는 함수
게시글은 여러개니까 List형태로 만든다.
public List<PostResponse> getContentInTitle(Long boardId) {
List<Post> byBoardId = postRepository.findByBoardId(boardId);
return byBoardId.stream().map(
post-> new PostResponse(
post.getTitle(),
post.getContent(),
post.getId(),
post.getCreatedAt())).toList();
}
이렇게 하면 하나의 게시판의 모든 게시글을 조회할 수 있다.
😐 느낀점
일단, 너무 힘드러~~~~~
관계를 맺었을 때는, 그 관계맺은 Id를 꼭 받아서 그걸 가지고 만들어야한다.
그걸 해주지 않아서 나는 1시간동안 애먹었음!