
이전 포스팅에서 CRUD 기능을 추상화해서 재사용 가능한 코드를 생성했다.
Reply 테이블의 CRUD를 추상화 코드로 변경해보자.
@Service
@RequiredArgsConstructor
public class ReplyService extends CRUDService<ReplyDTO, ReplyEntity> {}
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/reply")
public class ReplyApiController extends CRUDAbstractApiController<ReplyDTO, ReplyEntity> {}
매우 짧아졌다.
JpaRepository를 상속받는 Repository처럼 각 Reply의 클래스는 상속받는 추상클래스의 구현체를 자동으로 사용하게된다.
@Service
@RequiredArgsConstructor
public class ReplyConverter implements Converter<ReplyDTO,ReplyEntity> {
private final PostRepository postRepository;
@Override
public ReplyDTO toDTO(ReplyEntity replyEntity) {
return ReplyDTO.builder()
.id(replyEntity.getId())
.postId(replyEntity.getPost().getId())
.userName(replyEntity.getUserName())
.password(replyEntity.getPassword())
.status(replyEntity.getStatus())
.title(replyEntity.getTitle())
.content(replyEntity.getContent())
.repliedAt(replyEntity.getRepliedAt())
.build();
}
@Override
public ReplyEntity toENTITY(ReplyDTO replyDTO) {
var postEntity = postRepository.findById(replyDTO.getPostId());
return ReplyEntity.builder()
.id(replyDTO.getId())
.post(postEntity.orElseGet(()->null))
.userName(replyDTO.getUserName())
.password(replyDTO.getPassword())
.status((replyDTO.getStatus() != null) ? replyDTO.getStatus() : "REGISTERED")
.title(replyDTO.getTitle())
.content(replyDTO.getContent())
.repliedAt(
(replyDTO.getRepliedAt() != null) ? replyDTO.getRepliedAt() : LocalDateTime.now())
.build();
}
}
Converter 인터페이스에 존재하는 toENTITY를 구현하기만 하면 된다.
Converter는 과거 포스팅에도 기술했듯이 Controller레이어에 Entity가 보이는 것은 바람직하지 않기 때문에 DTO를 통해 데이터를 전송한다.
Repository레이어에 접근할 때 toENTITY메소드를 이용해 접근하도록 DTO를 Entity로 변환해야한다.
Entity로 변환할 때는 null값을 전송해서는 안된다. DTO와 Entity의 구조가 다를 수 있기 때문에 Entity 객체를 빌드할 때 null값이 내려가지 않도록 주의해야한다.

게시글 중 상품 하자의 불만이 있는 12번 id의 게시글에 reply를 달아보자

잘 게시되었으며, 기존에 구현하지 않았던 모든 답변 list를 조회해보자.

페이지까지 출력이 되고 reply 리스트가 출력이 된다.

id를 조회해 특정 reply를 열람할 수도 있다.