Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] 공연을 삭제할 때 발생하는 외래키 제약 예외 문제를 수정한다. #857

Closed
seokjin8678 opened this issue Apr 12, 2024 · 0 comments · Fixed by #858
Closed
Assignees
Labels
ADMIN BE 백엔드에 관련된 작업 🐛 버그 버그에 관련된 작업

Comments

@seokjin8678
Copy link
Collaborator

✨ 세부 내용

공연을 삭제하려고 하면 다음과 같이 외래키 제약 조건 예외가 발생하며 에러가 발생합니다.

[🔴ERROR] - (DELETE /admin/api/v1/stages/1)
(id: 1, role: ADMIN) org.springframework.dao.DataIntegrityViolationException: could not execute statement [Cannot delete or update a parent row: a foreign key constraint fails (`festago`.`stage_artist`, CONSTRAINT `fk_stage_artist__stage` FOREIGN KEY (`stage_id`) REFERENCES `stage` (`id`))] [delete from stage where id=?]; SQL [delete from stage where id=?]; constraint [null]
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:269)
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:229)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
	at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
	at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:243)

이유는 삭제 로직이 다음과 같이 구현되어 있기 때문인데

public void deleteStage(Long stageId) {
    stageRepository.findByIdWithFetch(stageId).ifPresent(stage -> {
        stageRepository.deleteById(stageId);
        stageArtistRepository.deleteByStageId(stageId);
        eventPublisher.publishEvent(new StageDeletedEvent(stage));
    });
}

해결 방법은 다음과 같이 stageArtistRepository.deleteByStageId() 메서드를 먼저 호출해야 합니다.

public void deleteStage(Long stageId) {
    stageRepository.findByIdWithFetch(stageId).ifPresent(stage -> {
        stageArtistRepository.deleteByStageId(stageId);
        stageRepository.deleteById(stageId);
        eventPublisher.publishEvent(new StageDeletedEvent(stage));
    });
}

StageDeleteServiceTest로 삭제되는 것이 검증이 되었지만, DB 구현체의 제약 조건으로 인해 해당 버그를 런타임 환경에서 확인할 수 있었네요. 😂
이래서 현업에서는 외래키 제약을 걸지 않는건가 싶기도 합니다.
(비즈니스 로직의 순서가 DB 구현체 때문에 순서가 강제됨)

⏰ 예상 소요 시간

10분

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ADMIN BE 백엔드에 관련된 작업 🐛 버그 버그에 관련된 작업
Projects
Status: Done
1 participant