앱에서 게시글 삭제 시 실패하는 이슈가 발생했다. 게시글 연관 데이터(이미지, 댓글, 신고)에 대한 처리를 고려하지 못해 발생한 문제였다.
게시글 삭제 시 연관 데이터를 자동으로 삭제하도록 수정했다.
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 레코드도 자동으로 삭제된다.
이 변경은 데이터베이스 스키마에 영구적으로 적용된다.
반응형
'Projects > 청하-청년을 위한 커뮤니티 서비스' 카테고리의 다른 글
[청하] 25. 청년 정책 데이터 리프레시 기능 구현 (0) | 2024.10.17 |
---|---|
[청하] 24. 청년 정책 Open API 연동 및 데이터베이스 저장 (feat. XML 데이터 매핑, 스케줄러 적용) (5) | 2024.10.17 |
[청하] 22. Android 강제 업데이트 검사 기능 - JWT 인증 필터에서 제외 (2) | 2024.10.16 |
[청하] 21. Android 강제 업데이트 버전 설정 기능 구현 (0) | 2024.10.16 |
[청하] 20. Android 강제 업데이트 검사 기능 구현 (0) | 2024.10.15 |
댓글