-
Nestjs-typeorm에서 트랜잭션 처리Nest.js 2023. 10. 10. 12:45728x90
대가리 진짜 아프다... 분명 아래 출처대로 했을때 잘 되다가 다른거 작업하고 오니까 다시 또 안된다
| TypeError: Cannot read properties of undefined (reading 'delete')
| at FeedsRepository.delete (/app/src/repository/Repository.ts:404:29)
| at FeedsRepository.deleteFeed (/app/src/models/repositories/feeds.repository.ts:70:41)
| at FeedsService.deleteFeed (/app/src/api/feeds/feeds.service.ts:77:6)
| at processTicksAndRejections (node:internal/process/task_queues:95:5)
| at FeedsController.deleteFeed (/app/src/api/feeds/feeds.controller.ts:100:3)대가리 뜨거워진다...
private readonly feedsRepository: FeedsRepository,
내가 사용하는 repository 패턴 사용을 위한 FeedsRepository
@Injectable() export class FeedsRepository extends Repository<FeedEntity> { constructor( @InjectRepository(FeedEntity) private readonly repository: Repository<FeedEntity>, ) { super(repository.target, repository.manager, repository.queryRunner); } ...
queryRunner.manager.withRepository(this.feedRepository)
이렇게 사용 했을 때 repository를 인식을 못한다
query: START TRANSACTION | FeedsRepository { | target: undefined, | manager: undefined, | queryRunner: undefined, | repository: Repository { | target: [class FeedEntity extends DefaultEntity], | manager: EntityManager { | '@instanceof': Symbol(EntityManager), | repositories: [Map], | treeRepositories: [], | plainObjectToEntityTransformer: PlainObjectToNewEntityTransformer {}, | connection: [DataSource] | }, | queryRunner: undefined | } | } | query: COMMIT
target과 manager queryRunner가 셋다 undefined가 뜬다.
그렇다면 커스텀 repository를 버리고 출력 했을땐 어떻게 될까
... @InjectRepository(FeedEntity) private readonly feedRepository: Repository<FeedEntity> ...
queryRunner.manager.withRepository(this.feedRepository)
Repository { | target: [class FeedEntity extends DefaultEntity], | manager: <ref *1> EntityManager { | '@instanceof': Symbol(EntityManager), | repositories: Map(0) {}, | treeRepositories: [], | plainObjectToEntityTransformer: PlainObjectToNewEntityTransformer {}, | connection: DataSource { | '@instanceof': Symbol(DataSource), | migrations: [], | subscribers: [], | entityMetadatas: [Array], | entityMetadatasMap: [Map], | name: 'default', | options: [Object], | logger: [AdvancedConsoleLogger], | driver: [PostgresDriver], | manager: [EntityManager], | namingStrategy: [DefaultNamingStrategy], | metadataTableName: 'typeorm_metadata', | queryResultCache: undefined, | relationLoader: [RelationLoader], | relationIdLoader: [RelationIdLoader], | isInitialized: true | }, | queryRunner: PostgresQueryRunner { | isReleased: false, | isTransactionActive: true, | data: {}, | loadedTables: [], | loadedViews: [], | sqlMemoryMode: false, | sqlInMemory: [SqlInMemory], | transactionDepth: 1, | cachedTablePaths: {}, | driver: [PostgresDriver], | connection: [DataSource], | mode: 'master', | broadcaster: [Broadcaster], | manager: [Circular *1], | databaseConnectionPromise: [Promise], | databaseConnection: [Client], | releaseCallback: [Function (anonymous)] | } | }, | queryRunner: undefined | } | query: COMMIT
이렇게 정상적으로 나오는걸 알 수 있다. 그럼 도대체 내껀 왜 안될까??
https://blog.naver.com/pjt3591oo/222927333364
해결방법
// service.ts constructor( .... private dataSource: DataSource, ) {} async deleteFeed(feedId: string) { // 피드가 있는지 확인. await this.findFeedByIdOrThrow(feedId); const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const [mediaStatus, feedStatus] = await Promise.all([ await this.mediasService.deleteFeedMediasByFeedId( feedId, queryRunner.manager, ), await this.feedsRepository.deleteFeed(feedId, queryRunner.manager), ]); if (!mediaStatus || !feedStatus) throw EntityConflictException(ERROR_DELETE_FEED_OR_MEDIA); const medias = await this.mediasService.findMediaUrlByFeedId(feedId); medias.map(async (media) => { const fileName = extractFilePathFromUrl(media.url, 'feed'); if (!fileName) throw EntityNotFoundException(ERROR_FILE_DIR_NOT_FOUND); await DeleteS3Media(fileName); }); await queryRunner.commitTransaction(); //s3에 미디어 파일들 삭제. } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } // repository.ts async deleteFeed(feedId: string, manager?: EntityManager) { if (manager) { const { affected } = await manager.delete(FeedEntity, { id: feedId, }); return !!affected; } const { affected } = await this.delete({ id: feedId, }); return !!affected; }
출처 -
https://inchan.dev/posts/202302250414/
https://orkhan.gitbook.io/typeorm/docs/custom-repository
https://blog.naver.com/pjt3591oo/222927333364
728x90'Nest.js' 카테고리의 다른 글
Nestjs에서 외부 api 호출할 때 HttpModule 사용 (0) 2023.11.15 Nestjs-TypeOrm에서 getRawMany 와 getMany (0) 2023.10.11 nestjs에서 multer, multer-s3, aws-sdk/client-s3로 멀티 업로드 (0) 2023.10.05 Nestjs+Nextjs 소켓 (0) 2023.09.16 Nestjs에서 mail 보내기 (0) 2023.08.16