본문 바로가기
Projects/청하-청년을 위한 커뮤니티 서비스

[청하] 23. 게시글 삭제 기능 - 외래키 제약 조건 수정

by Lpromotion 2024. 10. 16.

앱에서 게시글 삭제 시 실패하는 이슈가 발생했다. 게시글 연관 데이터(이미지, 댓글, 신고)에 대한 처리를 고려하지 못해 발생한 문제였다.

게시글 삭제 시 연관 데이터를 자동으로 삭제하도록 수정했다.

 

1. 프로젝트 구조

src/main/java/com/example/withpeace/
│
├── domain/                 # 도메인 모델 (엔티티)
│   ├── Image.java          # 이미지 엔티티
│   └── Post.java           # 게시글 엔티티
│
├── repository/                 # 데이터 접근 계층
│   ├── ImageRepository.java    # 이미지 레포지토리
│   └── PostRepository.java     # 게시글 레포지토리
│
├── controller/             # 컨트롤러 계층
│   └── PostController.java # 게시글 관련 API 엔드포인트
│
└── service/                # 비즈니스 로직 계층
    └── PostService.java    # 게시글 관련 비즈니스 로직

 

2. 도메인 수정

게시글 관련 엔티티에 `@OnDelete` 어노테이션을 추가하여 게시글 삭제 시 연관 데이터가 자동으로 삭제되도록 구현했다.

 

2.1. Comment 엔티티

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicUpdate
@Table(name = "comments")
public class Comment {
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE) // 추가
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "writer_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE) // 추가
    private User writer;

    // ... (기존 코드 생략)
    
}

 

2.2. Report 엔티티

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicUpdate
@Table(name = "reports")
public class Report {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id")
    @OnDelete(action = OnDeleteAction.CASCADE) // 추가
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE) // 추가
    private Comment comment;

    // ... (기존 코드 생략)
}

 

@OnDelete 어노테이션

`@OnDelete(action = OnDeleteAction.CASCADE)` 어노테이션은 연관 엔티티의 삭제 동작을 정의한다.

  • `action = OnDeleteAction.CASCADE`: 부모 엔티티(Post)가 삭제될 때 자식 엔티티(Comment, Report)도 같이 삭제된다.
  • `action = OnDeleteAction.NO_ACTION`: 디폴트 값이다. 부모 엔티티가 삭제될 때 아무 동작도 수행하지 않는다.

이 어노테이션을 사용하면 데이터베이스 레벨에서 `ON DELETE CASCADE` 제약 조건을 생성하도록 Hibernate에 지시한다.

 

3. 데이터베이스 스키마 변경 (MySQL)

`@OnDelete` 어노테이션을 추가하더라도 기존 데이터베이스에는 자동으로 반영되지 않기 때문에 데이터베이스 레벨에서 직접 외래키 제약 조건을 수정해야 한다.

 

3.1. 기존 외래키 제약 조건 확인 및 제거

기존 외래 키 제약 조건 이름을 확인하고 제거한다.

 

확인 명령어

SELECT 
    TABLE_NAME, 
    COLUMN_NAME, 
    CONSTRAINT_NAME, 
    REFERENCED_TABLE_NAME, 
    REFERENCED_COLUMN_NAME
FROM
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
    REFERENCED_TABLE_SCHEMA = 'database_name'
    AND REFERENCED_TABLE_NAME = 'posts';

 

제거 명령어

ALTER TABLE comments DROP FOREIGN KEY FKh4c7lvsc298whoyd4w9ta25cr;
ALTER TABLE reports DROP FOREIGN KEY FKneu1viyp671jjiwukyfv6dsy;
ALTER TABLE imagesDROP FOREIGN KEY FKcp0pycisii8ub3q4b7x5mfpn1;

 

3.2. 새로운 외래 키 제약 조건 추가

`ON DELETE CASCADE` 옵션이 포함된 새로운 외래키 제약 조건을 추가한다.

 

ALTER TABLE comments
ADD CONSTRAINT FKh4c7lvsc298whoyd4w9ta25cr
FOREIGN KEY (post_id)
REFERENCES posts(id)
ON DELETE CASCADE;
ALTER TABLE reports
ADD CONSTRAINT FKneu1viyp671jjiwukyfv6dsy
FOREIGN KEY (post_id)
REFERENCES posts(id)
ON DELETE CASCADE;
ALTER TABLE images
ADD CONSTRAINT FKcp0pycisii8ub3q4b7x5mfpn1
FOREIGN KEY (post_id)
REFERENCES posts(id)
ON DELETE CASCADE;

 

posts 테이블의 레코드를 삭제할 때 연관된 comments, reports, images 레코드도 자동으로 삭제된다.

이 변경은 데이터베이스 스키마에 영구적으로 적용된다.

반응형

댓글