
POST http://localhost:8080/api/v1/posts/2/comments
{
"timestamp": "2026-03-12T01:18:03.722Z",
"status": 500,
"error": "Internal Server Error",
"trace": "java.lang.NullPointerException: Cannot invoke \"java.lang.Integer.intValue()\" because the return value of \"com.back.domain.post.comment.entity.Comment.getId()\" is null\n\tat com.back.domain.post.comment.dto.CommentDto.<init>(CommentDto.java:15)\n\tat com.back.domain.post.comment.controller.ApiV1CommentController.create(ApiV1CommentController.java:78)
@PostMapping
@Transactional
public RsData<CommentWriteResBody> create(
@PathVariable int postId,
@RequestBody CommentWriteReqBody reqBody
){
Post post = postService.findById(postId).get();
Comment comment = post.addComment(reqBody.content);
postRepository.saveAndFlush(post);
return new RsData<>(
"%d번 댓글이 성공적으로 작성되었습니다.".formatted(comment.getId()),
"201-1",
new CommentWriteResBody(new CommentDto(comment))
);
}
왜 comment를 추가했는데 comment.getId()는 null을 반환할까?
→ JPA는 성능을 위해 쓰기 지연 (Transactional Write-behind) 을 한다.
메소드가 완전히 끝났을 때 트랜잭션이 커밋된다.
그래서 DB에 새로운 댓글이 반영되기 전에 comment.getId() 를 불러서 에러가 떴던 것이다.
posts.addComment 하면 메모리에 있는 리스트에 comment의 주소가 추가될 뿐이고, DB는 아직 insert문을 반영하지 않은 상태이다.
DB에 flush를 해줘야 RsData를 반환하기 전에 추가된 comment 객체를 DB에 반영할 수 있다.
해결: postRepository.flush();
유의해야할 것은 flush는 commit이 아니라 쿼리만 미리 해본다는 것이다. flush 하고 나서 아래쪽에서 에러가 나면, flush 했던 쿼리들도 깔끔하게 롤백된다.
근데? 댓글은 잘 추가되는데 404에러가 떴다.
@ResponseBody 가 없는 Controller 클래스는 return "index.html" 처럼 HTML 파일을 찾아서 띄우는데, return new RsData(...) 로 해당 이름의 HTML 파일이 없어 해당 리소스 파일이 없다는 404 에러를 띄운것이다.
@RestController 클래스에서는 자동으로 모든 메소드가 @ResponseBody 를 반환한다. 그래서 @RestController 로 바꿔준다.
추가 삽질 기록: @Transactional
테스트하다보니 @Transactional을 안 붙여도 댓글 저장이 잘만 됐다.
왜지? Transaction 이어야 DB에 반영이 되고 저장이 되는거 아닌가?
알아보니 extends JpaRepository 할때 SimpleJpaRepository의 transactional 설정을 사용하는데, save는 @Transactional이 적용되어 있기 때문이다.
By default, methods inherited from
CrudRepositoryinherit the transactional configuration fromSimpleJpaRepository.
출처: https://docs.spring.io/spring-data/jpa/reference/jpa/transactions.html