#PostgreSQL one-to-many relationship on TypeORM nested entity insertion, parent id null on subscriber

2 messages · Page 1 of 1 (latest)

errant plover
#

In one to many relationship on typeorm nested entity insertion subscriber on child recieves parent id as undefined.
Parent Entity:

@Entity('masterTemplate')
export class MasterTemplate extends BaseEntity {
  @PrimaryGeneratedColumn('uuid') id: string;

  @Column({
    type: 'varchar',

    nullable: false,

    unique: false,
  })
  name: string;

  @OneToMany(() => Program, (program) => program.masterTemplate, {
    cascade: true,
  })
  @JoinColumn({ name: 'id', referencedColumnName: 'masterTemplateId' })
  program: Program[];

  @OneToMany(() => UserProgram, (userProgram) => userProgram.masterTemplate, {
    cascade: true,
  })
  @JoinColumn({ name: 'id', referencedColumnName: 'masterTemplateId' })
  userProgram: UserProgram[];
}

Child Entity:


@Entity('program')
@Index(['masterTemplate', 'index'], { unique: true })
export class Program extends BaseEntity {

  @PrimaryGeneratedColumn('uuid') id: string;

  @Column({
    type: 'int4',

    nullable: false,
  })
  index: number;

  @Column({
    type: 'uuid',

    nullable: true,

    unique: false,
  })
  masterTemplateId: string;

  @Column({
    type: 'varchar',

    nullable: false,

    unique: false,
  })
  name: string;

  @OneToMany(() => Milestone, (milestone) => milestone.program, {
    cascade: true,
  })
  @JoinColumn({ name: 'id', referencedColumnName: 'programId' })
  milestone: Milestone[];

  @ManyToOne(() => MasterTemplate, (masterTemplate) => masterTemplate.program, {
    orphanedRowAction: 'delete',
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'masterTemplateId', referencedColumnName: 'id' })
  masterTemplate: MasterTemplate;

  @BeforeInsert()
  @BeforeUpdate()
  async updateIndex() {
    console.log('========================', this.masterTemplateId);
    if (!this.index) {
      const count = await Program.count({
        where: { masterTemplateId: this.masterTemplateId },
      });

      this.index = count + 1;
    }
  }
}
viscid barn
#

The issue you're facing with the nested entity insertion subscriber in TypeORM seems to be related to the undefined value of the masterTemplateId received by the child entity's BeforeInsert and BeforeUpdate hooks.

To resolve this issue, you can try modifying your child entity (Program) and the ManyToOne relationship decorator to specify the JoinColumn options more explicitly.

Child Entity (Program):

@Entity('program')
@Index(['masterTemplate', 'index'], { unique: true })
export class Program extends BaseEntity {
  // ...

  @ManyToOne(() => MasterTemplate, (masterTemplate) => masterTemplate.program, {
    orphanedRowAction: 'delete',
    onDelete: 'SET NULL',
    cascade: true, // Add this line
  })
  @JoinColumn({ name: 'masterTemplateId' }) // Remove referencedColumnName: 'id'
  masterTemplate: MasterTemplate;

  // ...
}

By specifying cascade: true in the ManyToOne relationship decorator, you can ensure that the parent entity (MasterTemplate) is cascaded to the child entity (Program) when inserted or updated.

Additionally, you can remove the referencedColumnName: 'id' option from the @JoinColumn decorator of the masterTemplate property in the Program entity. This will let TypeORM automatically infer the referenced column based on the primary key of the parent entity (MasterTemplate), which is id in this case.

These changes should help resolve the issue where the masterTemplateId is undefined in the child entity's hooks.