@GetMapping("/api/comment/{discussion_id}")
public ResponseEntity<?> getComment(@PathVariable long discussion_id) {
return service.getComment(discussion_id);
}
@GetMapping("/{discussion_id}")
public ResponseEntity<CommentResponseDto> getComment(@PathVariable long discussion_id) {
return service.getComment(discussion_id);
}
기존에 responseEntity를 만들어서 반환할때 어떤 유형이든 신경쓰지 않으려고 와일드 카드를 사용했었다.
다만 이 경우, controller만 봐서는 어떤 값이 반환될 지 한눈에 알기 힘들다는 문제가 있었기에 이를 명확하게 하고자 와일드 카드 부분을 모두 바꿔주었다.
public ResponseEntity<Void> updateComment(Long id, CommentUpdateDto updateDto) {
Comment comment = commentRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("해당 댓글이 없습니다. id= " + id));
comment.update(updateDto.getComment(), updateDto.getModifiedDate());
// return new ResponseEntity<>(HttpStatus.OK);
return ResponseEntity.ok().build();
}
현 프로젝트에는 매개변수가 많지 않아서 builder를 쓰나 객체를 쓰나 큰 차이가 없기 때문에 고민을 좀 했다.
다만, 확장성을 고려해봤을때 들어가게 되는 매개변수가 많아지면 builder 쪽이 좀 더 보기 편하므로 빌더를 사용하는 쪽으로 수정했다.
public record CommentUpdateDto(@NotBlank String comment) {
}
최근에 읽고 있는 책 내 코드가 이상한가요?에서 dto는 오로지 데이터를 온전히 전달하는 역할에 집중해야 한다고 나와있다.
때문에 dto의 인자들은 모두 불변하고 오직 getter로 값을 전달하는 역할만 하는데 이를 수행하기 적합한 것이 java 14버전에 추가된 레코드라고 생각해 dto들을 record로 바꿨다.
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class CommentService {
...
@Transactional
public ResponseEntity<Void> deleteComment(long id) {
commentRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
@Transactional 어노테이션을 붙이게 되면 해당 영역에서는 JPA의 스냅샷 유지, flush의 필요성, DB 커넥션을 오래 물고 있는 등의 관리적인 측면이 발생한다.
때문에 transactional readOnly로 두면 위의 기능들을 끌 수 있어 성능상의 이점이 발생할 수 있다.
다만 해당 기능이 필요한 경우도 있으므로 transactional 우선순위를 이용해서 클래스에 readonly를 주고 필요한 메서드에 transactional을 부여했다.
https://stackoverflow.com/questions/44151990/spring-responseentity-use-constructor-or-static-builder
https://colevelup.tistory.com/28
https://hungseong.tistory.com/74