Kevin Amiranoff
Kevin Amiranoff

Reputation: 14468

One-to-one relationship typeorm, save or update

I am trying to implement a one-to-one relationship with nestjs, typeorm and postgres.

I have a Profile Entity

  @OneToOne(() => Trainer, trainer => trainer.profile)
  @JoinColumn({ name: 'trainer_trainer_id' })
  trainer!: Trainer;

and a Trainer Entity

  @OneToOne(() => Profile, profile => profile.trainer)
  profile!: Profile;

When the user submits to become Trainer, I would like to update the database with a new row in the trainer table and add the associated id in the profile table.

So in the trainer repository I do:

  const trainer = CreateTrainerDto.toEntity(createTrainerDto);
    trainer.profile = profile;
    return await trainer.save();

this works well but it creates a new row in the trainer table every time (and updates accordingly the id in the profile table). but I was expecting save() to update an existing row if a trainer was already saved.

Am I doing it wrong?

Upvotes: 1

Views: 13106

Answers (2)

noam steiner
noam steiner

Reputation: 4444

The save method have two functionalities, insert and update.

If the provided entity instance have an id value it, update will execute, else insert.

Therefore, you can do the following:

const trainer = await this.trainerRepository.findOne(id) || this.trainerRepository.create(); // you can add the "or create" to have both create and update functionalities in one method
return await this.trainerRepository.save({...trainer, ...createTrainerDto, profile})

Upvotes: 3

binici
binici

Reputation: 915

When you call the save function on an entity, two things can happen:

  • If id is not set in the provided object, TypeORM will insert a new row in this table.
  • If id is set in the object, TypeORM will update the row corresponding to the referenced entity id.

Since your DTO is called createTrainerDto I assume you are not providing the id of the entity. This code will therefore always insert a new row in the table.

Create your DTOs so that the id property is optional, this way you can use the DTO for both creating and updating. For example:

export class TrainerDTO {
    id?: number;

    name: string;

    profile: ProfileDTO;
}

Upvotes: 2

Related Questions