- header 다듬기
- 각 페이지 UI 다듬기
- 게시글 작성 해도 작성일자가 안들어감.
public class Post {
...........
@CreationTimestamp
@Column(updatable = false)
private LocalDateTime createdAt;
...........
}
- 👉 import org.hibernate.annotations.CreationTimestamp; 필요
- DB에 insert 될 때 자동으로 현재 시간 저장됨
- @Column(updatable = false) → 수정 시 이 값은 변경되지 않도록 설정
- 게시글 수정 및 삭제
- 게시글 삭제 시 에러
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`emotracker`.`comment`, CONSTRAINT `FKs1slvnkuemjsq2kj4h3vhx7i1` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`))
-> 외래 키 제약 조건 오류 : 게시글(post)을 삭제하려 했는데, 그 게시글을 참조하는 댓글(comment) 이 아직 DB에 남아 있어서
삭제가 막힘.
1. controller
@PostMapping("/{id}/delete")
public String deletePost(@PathVariable Long id) {
postService.deletePost(id);
return "community";
}
2. service
@Transactional
public void deletePost(Long postId) {
commentRepository.deleteByPostId(postId); // 댓글 먼저
postRepository.deleteById(postId); // 게시글 삭제
}
@Transactional은 "이 메서드 안의 DB 작업은 하나의 트랜잭션으로 처리해줘" 라는 뜻
👉 이 두 개는 DB에 따로따로 명령을 보내는 거지만 @Transactional을 붙이면 아래처럼 처리돼:
✅ 하나의 트랜잭션으로 처리
- 댓글 삭제 성공
- 게시글 삭제 실패
→ 👉 댓글 삭제도 롤백(취소) 됨!
즉, 둘 중 하나라도 실패하면 전체 취소!
보통은 Service 계층에 붙임.
3. repository
@Modifying
@Query("DELETE FROM Comment c WHERE c.postId = :postId")
void deleteByPostId(@Param("postId") Long postId);
=> 에러
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'commentService' defined in file [C:\study\emotracker\emotracker\target\classes\com\emotracker\service\CommentService.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'commentRepository' defined in com.emotracker.repository.CommentRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract void com.emotracker.repository.CommentRepository.deleteByPostId(java.lang.Long); Reason: Validation failed for query for method public abstract void com.emotracker.repository.CommentRepository.deleteByPostId(java.lang.Long)
=> 지금 에러는 Spring Data JPA에서 메서드 이름으로 쿼리를 자동 생성할 때 생기는 대표적인 에러.
=> Could not create query for method deleteByPostId(Long)
👉 즉, deleteByPostId() 라는 메서드명에 맞는 쿼리를 못 만들겠어!
✅ 원인
Spring Data JPA는 메서드 이름만 보고 SQL을 자동으로 만들어주는데,
조건이 안 맞으면 쿼리를 못 만들어서 오류가 남.
📦 Comment 엔티티 예시
@Entity
public class Comment {
@ManyToOne
//@JoinColumn(name = "post_id")
// @JoinColumn(name = "post_id")를 생략하면 JPA가 기본 규칙대로 컬럼 이름을 자동으로 만들어주기 때문에
// @JoinColumn(name = "post_id")를 생략해도 무방함.
private Post post;
// ... 기타 필드들
}
✅ 정답부터 말하자면:
맞아! Comment 테이블에 postId라는 필드가 없기 때문에
c.postId는 컴파일 오류 + 쿼리 생성 실패의 원인이 되는 거야!
✅ 최종 정답 코드
@Modifying
@Transactional
@Query("DELETE FROM Comment c WHERE c.post.id = :postId")
// c.post.id Comment 테이블 → 연관된 post (comment엔티티의 post객체) → 그 Post 객체의 id
void deleteByPostId(@Param("postId") Long postId);
이건 연관 관계 필드를 통해 참조하는 올바른 방식이야!