보드와 포스트는 1:N 관계 (게시판에 여러개의 게시글이 올라올 수 있으니)
포스트와 리플라이는 1:N 관계 (게시글에 여러개의 댓글이 달릴 수 있다. )
JPA를 사용하게 되면
public List<ReplyEntity> findAllByPostId( Long postId){
return replyRepository.findAllByPostIdAndStatusOrderById(postId, "REGISTERED");
}
이러한 부분을 쉽게 오브젝트, ORM으로 활용이 가능하다. = 객체 지향적으로 데이터베이스를 컨트롤 하는 것이 가능해진다.
ORM?
객체 관계 매핑. JPA는 자바 클래스와 데이터의 테이블 간의 매핑을 지원한다. 이를 통해 복잡한 쿼리를 작성하지 않고 객체를 통해 데이터를 조작할 수 있다.
BoardController 추가:
@GetMapping("/id/{id}")
public BoardEntity view(@PathVariable Long id){
var entity = boardService.view(id);
log.info("result: {} ",entity);
return entity;
}
BoardEntity:
@OneToMany(mappedBy = "board") //1:N 관계를 나타내는 것.
//board는 postEntity에 있는 변수를 나타낸다.
//board 를 select하게 되면 postEntity가 내려오게 된다.
private List<PostEntity> postList = List.of();
post와 관계를 설정해준다.
BoardService:
public BoardEntity view(Long id) {
return boardRepository.findById(id).get();
}
PostEntity:
//BoardEntity에서 설정한 것에 따라 변경. 객체로 변경된 것
@ManyToOne //내가 N
@JsonIgnore //무한생성 없애기,관계 끊어주기
@ToString.Exclude //log.info 무한 생성 없애기. 관계 끊어주기
private BoardEntity board; //시스템상 + _id를 붙이기 때문에 board_id가 된다.
Board와 관계를 설정해준다.
PostEntity:
private Long boardId =1L;
PostService 추가, 수정
private final BoardRepository boardRepository;
public PostEntity create(PostRequest postRequest) {
var boardEntity = boardRepository.findById(postRequest.getBoardId()).get();//임시 고정값
var entity = PostEntity.builder()
.board(boardEntity)
하지만 이 방법은 무한 생성을 만들어내 관계를 끊어 무한반복 없애는 어노테이션을 썼다. 하지만 이는 근본적인 해결책이 아님
결론적인 이유는?
ToString 을 찍어서.
Json으로 내려오면 안되는 Entity가 뷰까지 내려가면서 문제가 생긴다.
해결책= Entity를 내리는 것이 아니라 뷰에 내릴 Dto만들어 내리기
model - boardDto, postEto 생성.
기본적으로 Entity와 비슷하게 생겼지만 @OneToMany, @Id 같은 관계 없음
package com.example.myboard.post.model;
import com.example.myboard.board.db.BoardEntity;
import com.example.myboard.reply.db.ReplyEntity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class PostDto {
private Long id;
private Long boardId; //시스템상 + _id를 붙이기 때문에 board_id가 된다.
private String userName;
private String password;
private String status;
private String title;
private String content;
private LocalDateTime postedAt;
}
package com.example.myboard.board.model;
import com.example.myboard.post.db.PostEntity;
import com.example.myboard.post.model.PostDto;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.persistence.*;
import lombok.*;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class BoardDto {
private Long id;
private String boardName;
private String status;
private List<PostDto> postList = List.of();
}
Dto를 변환 시켜주는 것이 필요함 -> Converter
Service - BoardConverter 생성
컨버터의 역할은 데이터를 변환하는 것.
public BoardEntity create(BoardRequest boardRequest){
var entity = BoardEntity.builder()
.boardName(boardRequest.getBoardName())
.status("REGISTERED")
.build();
return boardRepository.save(entity);
}
이러한 로직을 컨버터로 몰아준다.
더 이상 entity를 리턴하지 않는다. dto를 리턴해준다.
DTo를 설정하면 연관관계를 설정하더라도 무한 반복이 되는 방식을 피해준다.
entity를 뷰까지 내리는 일은 없어야 하고 Dto를 내려준다. 그렇기 위해서는 entity와 상응하는 dto를 만들어줘야 한다.
만든 dto를 내려주기 위해선 converter를 통해 데이터 변환을 해준다.
package com.example.myboard.board.service;
import com.example.myboard.board.db.BoardEntity;
import com.example.myboard.board.model.BoardDto;
import com.example.myboard.post.service.PostConverter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class BoardConverter {
//postList를 바꿔줘야하는데 -> PostConverter
private final PostConverter postConverter;
//BoardEntity 가 들어오면 BoardDto로 바꿔준다.
public BoardDto toDto(BoardEntity boardEntity){
// entity를 dto로 바꿔준다.
var postList = boardEntity.getPostList()
.stream()
.map(postConverter::toDto)
.collect(Collectors.toList());
//이 코드는 BoardEntity 객체에서 getPostList() 메서드를 사용하여 게시물 리스트를 가져온 후,
// 이를 스트림으로 변환합니다.
// 그런 다음 각 게시물에 대해 postConverter::toDto 메서드를 사용하여
// DTO(Data Transfer Object)로 변환하고,
// 이를 모두 리스트로 수집합니다.
return BoardDto.builder()
.id(boardEntity.getId())
.boardName(boardEntity.getBoardName())
.status(boardEntity.getStatus())
.postList(postList)
.build();
}
}
package com.example.myboard.post.service;
import com.example.myboard.post.db.PostEntity;
import com.example.myboard.post.model.PostDto;
import org.springframework.stereotype.Service;
@Service
public class PostConverter {
public PostDto toDto(PostEntity postEntity){
return PostDto.builder()
.id(postEntity.getId())
.boardId(postEntity.getBoard().getId())
.title(postEntity.getTitle())
.userName(postEntity.getUserName())
.status(postEntity.getStatus())
.content(postEntity.getContent())
.postedAt(postEntity.getPostedAt())
.build();
}
}
BoardController 수정해준다.
@PostMapping("")
public BoardEntity create(@Valid @RequestBody BoardRequest boardRequest){
return boardService.create(boardRequest);
}
@GetMapping("/id/{id}")
public BoardEntity view(@PathVariable Long id){
var entity = boardService.view(id);
log.info("result: {} ",entity);
return entity;
}
BoardService도 수정해준다.
public class BoardService {
private final BoardRepository boardRepository;
private final BoardConverter boardConverter;
public BoardDto create(BoardRequest boardRequest){
var entity = BoardEntity.builder()
.boardName(boardRequest.getBoardName())
.status("REGISTERED")
.build();
var saveEntity = boardRepository.save(entity);
return boardConverter.toDto(saveEntity);
}
public BoardDto view(Long id) {
var entity =boardRepository.findById(id).get();
return boardConverter.toDto(entity); //converter를 사용해 dto로 바꿔준다.
}
}
현재 패키지 구조
'JAVA > 프로젝트' 카테고리의 다른 글
MVC 기반 온라인 쇼핑 카트 구현하기: DB 설계 (0) | 2024.05.05 |
---|---|
Spring Boot: JPA 연관관계 설정하기 -2, 최신순 정렬, 삭제된 게시글 제외 하고 조회 (0) | 2024.04.27 |
Spring Boot: End point 개발 3, 게시글과 게시글에 달린 답변 같이 보기 (0) | 2024.04.27 |
Spring Boot: End point 개발 2, 조회, 개별 조회, 삭제 (0) | 2024.04.27 |
Spring Boot : 게시판 End point 개발. board와 post 생성 (0) | 2024.04.26 |