From e4bb68d447a22789927f26086ae13dab0720ab7a Mon Sep 17 00:00:00 2001 From: SungHyun Do <52828205+glaxyt@users.noreply.github.com> Date: Fri, 13 Dec 2024 05:07:26 +0900 Subject: [PATCH] =?UTF-8?q?[BE=20-#168]=20=EB=B2=8C=ED=81=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=A1=9C=EC=A7=81=20=EC=B1=85=EC=9E=84=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20(#169)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 서비스 레이어에서의 벌크 삭제 로직 역할 분리 * refactor: quiz 테이블 명시 * refactor: 분리된 벌크 삭제 메서드를 트랜잭션과 함께 구현 --- .../quiz/quizzes/entities/quiz.entity.ts | 22 ++++++++-------- .../src/module/quiz/quizzes/quiz.service.ts | 7 ++++- .../quizzes/repositories/choice.repository.ts | 18 +++++-------- .../quizzes/repositories/class.repository.ts | 26 +++---------------- .../quizzes/repositories/quiz.repository.ts | 4 +++ 5 files changed, 30 insertions(+), 47 deletions(-) diff --git a/packages/server/src/module/quiz/quizzes/entities/quiz.entity.ts b/packages/server/src/module/quiz/quizzes/entities/quiz.entity.ts index 56a765c4..30f7f028 100644 --- a/packages/server/src/module/quiz/quizzes/entities/quiz.entity.ts +++ b/packages/server/src/module/quiz/quizzes/entities/quiz.entity.ts @@ -3,7 +3,7 @@ import { QuizType } from '../utils/quiz-type.enum'; import { Choice } from './choice.entity'; import { Class } from './class.entity'; -@Entity() +@Entity('quiz') export class Quiz { @PrimaryGeneratedColumn() id: number; @@ -15,10 +15,10 @@ export class Quiz { content: string; @Column({ - name: 'quiz_type', - type: 'enum', - enum: QuizType, - default: QuizType.TF, + name: 'quiz_type', + type: 'enum', + enum: QuizType, + default: QuizType.TF, }) quizType: QuizType; @@ -29,18 +29,18 @@ export class Quiz { point: number; @Column() - position: number + position: number; @Column({ name: 'created_at' }) createdAt: Date; - @OneToMany(() => Choice, choice => choice.quiz, { + @OneToMany(() => Choice, (choice) => choice.quiz, { cascade: true, - eager: false + eager: false, }) choices: Choice[]; - @ManyToOne(() => Class, cls => cls.quizzes) - @JoinColumn({ name: 'class_id' }) + @ManyToOne(() => Class, (cls) => cls.quizzes) + @JoinColumn([{ name: 'class_id', referencedColumnName: 'id' }]) class: Class; -} \ No newline at end of file +} diff --git a/packages/server/src/module/quiz/quizzes/quiz.service.ts b/packages/server/src/module/quiz/quizzes/quiz.service.ts index 39f9dc88..721f1c50 100644 --- a/packages/server/src/module/quiz/quizzes/quiz.service.ts +++ b/packages/server/src/module/quiz/quizzes/quiz.service.ts @@ -106,6 +106,11 @@ export class QuizService { } async deleteClass(id: number): Promise { - await this.classRepository.deleteWithRelations(id); + return this.dataSource.transaction(async (manager) => { + await this.classRepository.findClassById(id); + await this.choiceRepository.deleteByClassId(id, manager); + await this.quizRepository.deleteByClassId(id, manager); + await this.classRepository.delete(id, manager); + }); } } diff --git a/packages/server/src/module/quiz/quizzes/repositories/choice.repository.ts b/packages/server/src/module/quiz/quizzes/repositories/choice.repository.ts index de889c8d..20171b36 100644 --- a/packages/server/src/module/quiz/quizzes/repositories/choice.repository.ts +++ b/packages/server/src/module/quiz/quizzes/repositories/choice.repository.ts @@ -11,11 +11,7 @@ export class ChoiceRepository { private readonly repository: Repository, ) {} - async create( - quizId: number, - choiceData: CreateChoiceRequestDto, - manager?: EntityManager, - ): Promise { + async create(quizId: number, choiceData: CreateChoiceRequestDto): Promise { const { content, isCorrect, position } = choiceData; const choiceEntity = this.repository.create({ quizId, @@ -72,12 +68,10 @@ export class ChoiceRepository { } } - async deleteByQuizId(quizId: number, manager?: EntityManager): Promise { - const repo = manager ? manager.getRepository(Choice) : this.repository; - try { - await repo.delete({ quizId }); - } catch (error) { - throw new InternalServerErrorException('Failed to delete choices'); - } + async deleteByClassId(classId: number, manager: EntityManager): Promise { + await manager.query( + 'DELETE FROM choice WHERE quiz_id IN (SELECT id FROM quiz WHERE class_id = ?)', + [classId], + ); } } diff --git a/packages/server/src/module/quiz/quizzes/repositories/class.repository.ts b/packages/server/src/module/quiz/quizzes/repositories/class.repository.ts index 6ab4da5e..b5f898ec 100644 --- a/packages/server/src/module/quiz/quizzes/repositories/class.repository.ts +++ b/packages/server/src/module/quiz/quizzes/repositories/class.repository.ts @@ -1,6 +1,6 @@ import { Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { DataSource, Repository } from 'typeorm'; +import { DataSource, EntityManager, Repository } from 'typeorm'; import { Class } from '../entities/class.entity'; @Injectable() @@ -128,27 +128,7 @@ export class ClassRepository { } } - async deleteWithRelations(id: number): Promise { - const queryRunner = this.dataSource.createQueryRunner(); - await queryRunner.connect(); - await queryRunner.startTransaction(); - - try { - await queryRunner.query( - `DELETE FROM choice WHERE quiz_id IN (SELECT id FROM quiz WHERE class_id = ?)`, - [id], - ); - - await queryRunner.query(`DELETE FROM quiz WHERE class_id = ?`, [id]); - - await queryRunner.query(`DELETE FROM class WHERE id = ?`, [id]); - - await queryRunner.commitTransaction(); - } catch (error) { - await queryRunner.rollbackTransaction(); - throw new InternalServerErrorException('Failed to delete'); - } finally { - await queryRunner.release(); - } + async delete(id: number, manager: EntityManager): Promise { + await manager.delete(Class, { id }); } } diff --git a/packages/server/src/module/quiz/quizzes/repositories/quiz.repository.ts b/packages/server/src/module/quiz/quizzes/repositories/quiz.repository.ts index cb3db41b..50c0ad17 100644 --- a/packages/server/src/module/quiz/quizzes/repositories/quiz.repository.ts +++ b/packages/server/src/module/quiz/quizzes/repositories/quiz.repository.ts @@ -198,4 +198,8 @@ export class QuizRepository { await queryRunner.release(); } } + + async deleteByClassId(classId: number, manager: EntityManager): Promise { + await manager.query('DELETE FROM quiz WHERE class_id = ?', [classId]); + } }