TIL

23/12/26 TIL __ typeOrm 에서 트랜젝션 처리하기

GABOJOK 2023. 12. 26. 23:59

 

 

트랜잭션이란.

간단하게 말하면 다 실행되거나 다 실패하거나 이다. 

 

typeOrm에서는 어떻게 처리하는지 살펴보자. 

 

먼저 typeOrm 에서는 다양한 방식을 지원하고 있지만 나의 경우 쿼리빌더 방식을 사용했다. 

 

 

  //한번에 트랜젝션으로 권한변 회원 로그인 처리
  async registerAndCreateDetail(registerDto): Promise<object> {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    //기본정보 회원가입
    const { role, email, password } = registerDto;
    const detailDto = registerDto.customerDetailDto
      ? registerDto.customerDetailDto
      : registerDto.performerDetailDto;

    const existingUser = await queryRunner.manager.getRepository(User).findOne({
      where: { email },
    });
    //사용자는 동일한 이메일 주소로 각각의 권한을 소유할 수 있다.
    if (existingUser) {
      if (existingUser.role === role) {
        throw new ConflictException(
          '선택하신 권한으로 이미 존재하는 이메일이 있습니다.',
        );
      }
    }
    try {
      //기본정보 회원가입 데이터 베이스 넣기.
      let userDetail: Promise<CustomerDetailDto | PerformerDetailDto>;
	  const hashedPassword = await hash(password, 10);
        const userRegister = await queryRunner.manager
          .getRepository(User)
          .save({
            role,
            email,
            password: hashedPassword,
          });
        return { userRegister, userDetail };
      }
      if (role === 'CUSTOMER') {
        // throw new Error('테스트');
        userDetail = await queryRunner.manager
          .getRepository(CustomerDetail)
          .save({
            ...detailDto,
            user: userRegister,
          });
      } else if (role === 'PERFORMER') {
        userDetail = await queryRunner.manager
          .getRepository(PerformerDetail)
          .save({
            ...detailDto,
            user: userRegister,
          });

      await queryRunner.commitTransaction();
    } catch (err) {
      console.log(err);
      await queryRunner.rollbackTransaction();
    } finally {
      await queryRunner.release(); // 성공하던, 실패하던 언제나 쿼리러너 해재. 메모리누수,리소스낭비 방지.
    }
  }

 

 

 

 

처음에 컨스트럭터에 주입할때 계속 문제가 있었는데, 이부분은 순서가 중요하다.

 constructor(
    @InjectRepository(PerformerDetail)
    private performerDetailRepository: Repository<PerformerDetail>,
    @InjectRepository(CustomerDetail)
    private customerDetailRepository: Repository<CustomerDetail>,
    private readonly jwtService: JwtService,
    private dataSource: DataSource,
) {}


//이렇게 쓰면 안됨.
constructor(
    @InjectRepository(PerformerDetail)
    @InjectRepository(CustomerDetail)
    private performerDetailRepository: Repository<PerformerDetail>,
    private customerDetailRepository: Repository<CustomerDetail>,
    private readonly jwtService: JwtService,
    private dataSource: DataSource,
) {}

 

 

이렇게 해서 회원가입을 트랜젝션으로 처리를 했는데, 해당 설정에서 막혀 테이블을 결국 분리하게 되었다...