본문 바로가기

포트폴리오 만들기/spring boot, jpa emo 기록하기

11일차 메뉴 및 UI 수정, 게시글 수정 및 삭제

반응형

- 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);

이건 연관 관계 필드를 통해 참조하는 올바른 방식이야!

 

 

반응형

'포트폴리오 만들기 > spring boot, jpa emo 기록하기' 카테고리의 다른 글

12일차  (0) 2025.04.23
10일차  (0) 2025.04.20
7, 8, 9일차  (0) 2025.04.20
6일차  (0) 2025.04.19
4, 5일차  (1) 2025.04.19