Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ public ApiResponse<AdminResponseDTO.CreateQuizResponseDTO> createQuiz(
return ApiResponse.ok(result);
}

@DeleteMapping("/quiz/{quizId}")
@Operation(summary = "퀴즈 삭제 API")
public ApiResponse<Boolean> deleteQuiz(@PathVariable Long quizId) {
Boolean success = adminService.deleteQuiz(quizId);
return ApiResponse.ok(success);
}

@PostMapping("/keywords")
@Operation(summary = "일일 키워드 등록 API")
public ResponseEntity<ApiResponse<DailyKeywords>> createKeyword(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.example.cp_main_be.domain.reports.domain.Reports;
import com.example.cp_main_be.domain.reports.domain.repository.ReportRepository;
import com.example.cp_main_be.domain.reports.enums.ReportStatus;
import com.example.cp_main_be.global.exception.QuizNotFoundException;
import com.example.cp_main_be.global.infra.S3Uploader;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -91,6 +92,13 @@ public AdminResponseDTO.CreateQuizResponseDTO createQuiz(
.build();
}

@Transactional
public boolean deleteQuiz(Long quizId) {
Quiz quiz = quizRepository.findById(quizId)
.orElseThrow(() -> new QuizNotFoundException("퀴즈가 존재하지 않습니다."));
quizRepository.delete(quiz);
return true;
}
Comment on lines +95 to +101
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

연관 엔티티(QuizOptions 등) 삭제 보장 필요 — FK 제약 위반/고아 레코드 위험

현재 Quiz만 삭제합니다. Quiz ↔ QuizOptions, DailyMissionMaster ↔ Quiz 등 연관관계에서

  • JPA 매핑에 orphanRemoval = true 또는 CascadeType.REMOVE가 없다면 FK 제약 위반이 발생할 수 있고,
  • DB FK에 ON DELETE CASCADE가 없다면 자식 레코드가 남을 수 있습니다.

엔티티 매핑 또는 DB 제약을 점검/보완해주세요. 없다면 다음과 같이 매핑을 권장합니다(참고용, 엔티티 파일에서 적용).

// in Quiz.java
@OneToMany(mappedBy = "quiz", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<QuizOptions> options;

또는 서비스 계층에서 명시적으로 자식부터 삭제하는 전략을 택할 수 있습니다.

아래 스크립트로 매핑 상태를 빠르게 점검해볼 수 있습니다.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Quiz 엔티티 정의 위치 =="
rg -nP --type=java -C3 'class\s+Quiz\b'

echo "== Quiz -> QuizOptions @OneToMany 매핑 확인 =="
rg -nP --type=java -n -C2 '@OneToMany\([^)]*\)\s+private\s+List<\s*QuizOptions\s*>'

echo "== QuizOptions에서 @ManyToOne(Quiz) 매핑 확인 =="
rg -nP --type=java -n -C3 'class\s+QuizOptions\b'
rg -nP --type=java -n -C3 '@ManyToOne[^\n]*\n\s*private\s+Quiz\b'

echo "== orphanRemoval 또는 CascadeType.REMOVE 존재 여부 =="
rg -nP --type=java -n 'orphanRemoval\s*=\s*true|CascadeType\.REMOVE|CascadeType\.ALL'

echo "== SQL 마이그레이션에서 FK 및 ON DELETE CASCADE 확인(있다면) =="
fd -t f -e sql | xargs -r rg -n 'QuizOptions|quiz_options|FOREIGN KEY|ON DELETE'

Length of output: 979


추가 검증을 위해 오류 발생 시에도 계속 진행하도록 스크립트를 수정했습니다. 아래 스크립트를 실행한 후 결과를 공유해주세요.


🏁 Script executed:

#!/bin/bash
echo "== Quiz.java 내 @OneToMany 매핑 확인 =="
rg -nP --type=java -n -C2 '@OneToMany' src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/Quiz.java || echo "  → 매핑 없음"

echo
echo "== Quiz.java 내 orphanRemoval/CascadeType 설정 확인 =="
rg -nP --type=java -n 'orphanRemoval\s*=\s*true|CascadeType\.REMOVE|CascadeType\.ALL' src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/Quiz.java || echo "  → 설정 없음"

echo
echo "== QuizOptions.java 내 @ManyToOne 매핑 확인 =="
rg -nP --type=java -n -C2 '@ManyToOne' src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/QuizOptions.java || echo "  → 매핑 없음"

echo
echo "== QuizOptions.java 내 orphanRemoval/CascadeType 설정 확인 =="
rg -nP --type=java -n 'orphanRemoval\s*=\s*true|CascadeType\.REMOVE|CascadeType\.ALL' src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/QuizOptions.java || echo "  → 설정 없음"

echo
echo "== SQL 마이그레이션에서 quiz_options FK 및 ON DELETE CASCADE 확인 =="
fd -t f -e sql | xargs -r rg -n -C1 'FOREIGN KEY.*quiz_options|ON DELETE CASCADE' || echo "  → 관련 정의 없음"

Length of output: 1463


추가로 DailyMissionMaster ↔ Quiz 매핑 상태도 확인할 수 있도록 아래 스크립트를 실행해주세요.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== DailyMissionMaster 클래스 위치 =="
rg -nP --type=java -C2 'class\s+DailyMissionMaster\b' src || echo "  → DailyMissionMaster 파일 없음"

echo
echo "== DailyMissionMaster -> Quiz @ManyToOne 매핑 확인 =="
rg -nP --type=java -n -C2 '@ManyToOne.*\bQuiz\b' $(rg -lP 'DailyMissionMaster' -g '*.java') || echo "  → 매핑 없음"

echo
echo "== DailyMissionMaster 내 orphanRemoval/CascadeType 설정 확인 =="
rg -nP --type=java -n 'orphanRemoval\s*=\s*true|CascadeType\.REMOVE|CascadeType\.ALL' $(rg -lP 'DailyMissionMaster' -g '*.java') || echo "  → 설정 없음"

echo
echo "== Quiz.java 내 @OneToMany → DailyMissionMaster 매핑 확인 =="
rg -nP --type=java -n -C2 '@OneToMany.*\bDailyMissionMaster\b' src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/Quiz.java || echo "  → 매핑 없음"

echo
echo "== SQL 마이그레이션에서 daily_mission_master FK 및 ON DELETE CASCADE 확인 =="
fd -t f -e sql | xargs -r rg -n -C1 'FOREIGN KEY.*daily_mission_master|ON DELETE CASCADE' || echo "  → 관련 정의 없음"

Length of output: 5081


연관 엔티티 삭제 매핑 추가 필요

현재 deleteQuiz 메서드는 Quiz 엔티티만 삭제하며, 다음과 같은 위험이 있습니다.

  • JPA에서 QuizOptions(Quiz ↔ QuizOptions) 연관관계에 cascade 또는 orphanRemoval 설정이 없어, 부모 삭제 시 FK 제약 위반 또는 자식 레코드 고아 상태 발생
  • DB 마이그레이션에 quiz_options 테이블의 FK에 ON DELETE CASCADE 설정이 없음
  • (DailyMissionMaster ↔ Quiz 관계가 실제로 존재한다면) 해당 매핑도 누락되어 동일한 위험

점검 결과

  • Quiz.java: @OneToMany 매핑 정의 없음
  • QuizOptions.java: @ManyToOne만 있고 cascade/orphanRemoval 설정 없음
  • SQL 마이그레이션: FOREIGN KEY … quiz_options / ON DELETE CASCADE 정의 없음
  • DailyMissionMaster.java ↔ Quiz 매핑 없음 (필요 시 검토)

조치 방안

  • src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/Quiz.java에 자식 엔티티 매핑 추가 (예시)
    @OneToMany(mappedBy = "quiz", cascade = CascadeType.REMOVE, orphanRemoval = true)
    private List<QuizOptions> options;
  • 서비스 계층에서 자식부터 명시적으로 삭제하거나
  • DB 스키마에 FK 제약과 ON DELETE CASCADE 설정 추가
  • DailyMissionMaster ↔ Quiz 관계가 실제로 필요하다면, 유사하게 JPA 매핑/DB 제약 보완
🤖 Prompt for AI Agents
In src/main/java/com/example/cp_main_be/domain/admin/service/AdminService.java
around lines 95–101, deleteQuiz currently deletes only the Quiz entity which can
leave orphaned QuizOptions or violate FK constraints; update the domain and/or
schema to cascade deletions: add a OneToMany mapping in
src/main/java/com/example/cp_main_be/domain/mission/quiz/domain/Quiz.java for
QuizOptions with mappedBy set to the Quiz field and set cascade =
CascadeType.REMOVE and orphanRemoval = true (or CascadeType.ALL if appropriate),
or alternatively modify the service to explicitly delete child QuizOptions
before deleting the Quiz; add/adjust the DB migration to set the foreign key on
quiz_options to ON DELETE CASCADE; and if DailyMissionMaster has a relation to
Quiz, add the corresponding JPA mapping and DB FK cascade or handle deletions
similarly.

// DailyMissionMasters 생성
@Transactional
public DailyMissionMaster createDailyMissionMasters(
Expand Down
Loading