TypeOrm不会在更新时保存实体及其关系

时间:2019-08-28 12:48:51

标签: postgresql typescript nestjs typeorm

给出以下关系:

@Entity({name: 'accounts'})
export class Account {

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @OneToOne(type => Address, address => address.id)
  @JoinColumn({name: 'address_id'})
  address: Address;

  @Column()
  name: string;
}

与addres关系:

@Entity({name: 'addresses'})
export class Address {

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({length: 45})
  country: string;
}

当我以此获得account实体时:

  /**
   * Gets account by haccount ID with ALL relations
   * @param accountId The account ID
   */
  public async getAccountByAccountIdWithRelations(accountId: string): Promise<Account> {
    return await this.findOneOrFail({id: accountId}, {relations: ['address']});
  }

我得到了其中具有Account关系的完整Address实体。

然后执行以下操作:

account.address.country = 'newcountry';

并在this.save(account)中执行accountRepository,地址根本不会更新!

在保存之前执行控制台日志时,我看到带有更新地址的account实体,所以这真的很奇怪!

为什么会这样?

注意:所有查询都在事务中完成;我不知道这是否重要

2 个答案:

答案 0 :(得分:1)

应设置级联。这是我的实体的一个示例:

@Entity()
@Index([ 'studyId', 'teamId', 'enterdate' ])
export class DataMessage extends BaseEntity {
    @PrimaryGeneratedColumn('increment') id: number;

    @CreateDateColumn() enterdate: Date;
    @UpdateDateColumn({ select: false })
    updatedAt?: Date;
    @Column() owner: string;
    @Column() studyId: number;
    @Column() teamId: number;
    @Column() patient: string;
    @Column() orderId: number;
    @Column({ default: DataMessageStatus.OPEN })
    status: DataMessageStatus;

    @Column()
    @Index()
    resultId: number;

    @OneToMany(() => DataMessageContent, (c) => c.message, { cascade: true })
    contents: DataMessageContent[];
}

@Entity()
export class DataMessageContent extends BaseEntity {
    @PrimaryGeneratedColumn('increment') id: number;

    @CreateDateColumn() enterdate: Date;
    @Column() owner: string;
    @Column() role: UserRole;
    @Column({ default: MessageStatus.UNREAD })
    status: MessageStatus;

    @Column() txt: string;

    @ManyToOne(() => DataMessage, (m) => m.contents)
    message: DataMessage;
}

这也应该适用于一对一关系。

答案 1 :(得分:0)

在sql上进行这种更新非常复杂,即使使用queryBuilder TypeORM,它也不支持联接更新(您可以here看到它)。关系选择器很有帮助,但是我建议您在确实需要它时使用它,并添加一个可为空的字段以获取地址的ID并单独获取地址,这样在您需要更改内容的情况下,事情变得容易得多关系让您说出何时要更改整个地址对象。这将是关系的结果:

@Entity({name: 'accounts'})
export class Account {

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ nullable: true })
  address_id: string;

  @OneToOne(type => Address, address => address.id)
  @JoinColumn({name: 'address_id'})
  address: Address;

  @Column()
  name: string;
}

您可以像以前一样继续调用该关系:

public async getAccountByAccountIdWithRelations(accountId: string): Promise<Account> {
    return await this.findOneOrFail({id: accountId}, {relations: ['address']});
  }

使用此方法将使插入和更新变得容易,并且在oneToMany => manyToOne关系中也可以使用