Search code examples
transactionssql-updatenestjstypeorm

TypeOrm Do I need to useTransaction when updating an entity with multiple one to many relations


I have a Company class with the following definition:

export class Company extends BaseEntity {
  @PrimaryGeneratedColumn()
  @Field((type) => ID) // needed to overwrite the number typ
  id: number;

  @Column()
  name: string;

  @Column()
  domain: string;

  @OneToMany(() => User, (user) => user.company, {
    onDelete: 'SET NULL',
  })
  users: User[];

  @OneToMany(() => Deal, (deal) => deal.company)
  deals: Deal[];
}

and when updating a company, the update company dto would contain both a list of dealIds as well as userIds to add to the existing relations. Here is my update method:

async update(id: number, updateCompanyInput: UpdateCompanyInput) {
    console.log(`This action updates a #${id} company`);
    const queryRunner = this.connection.createQueryRunner();
    await queryRunner.connect();

    const company = await queryRunner.manager.preload(Company, {
      id,
      ...updateCompanyInput,
    });
    
    await queryRunner.manager
      .createQueryBuilder()
      .relation(Company, 'users')
      .of(id)
      .add(updateCompanyInput.userIds);

    await queryRunner.manager
      .createQueryBuilder()
      .relation(Company, 'deals')
      .of(id)
      .add(updateCompanyInput.dealIds);

    const result = this.companyRepository.save(company);
    await queryRunner.release();
    return result;
  }

I am wondering:

  1. Do I need to use a transaction (https://orkhan.gitbook.io/typeorm/docs/transactions)?
  2. Do I need to call queryRunner.release() after this.companyRepository.save or the order can be more flexible?

Solution

  • You do not need to use a transaction. You should use a transaction if and only if you want to undo the added Company, 'users' relation when something goes wrong adding the Company, 'deals' relation. Transactions are just a way of making the queries within it atomic (ie all occur or none occur).

    As far as query runner releasing - I'm not sure. I haven't used query runner at all. I'm not sure why you are, actually, so maybe this is a bad answer? I use getRepository for everything. ie either getRepository(Company).createQueryBuilder('company')

    Or

    getRepository(Company).find('primary key value')

    should both work, assuming you create the connection on server startup.