【问题标题】:TypeOrm doesn't save entity with it's relation on updateTypeOrm 不会在更新时保存实体及其关系
【发布时间】:2020-01-01 16:58:02
【问题描述】:

给定以下关系:

@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;
}

和地址关系:

@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';

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

当我在保存前做控制台日志时,我看到 account 实体的地址已更新,所以这真的很奇怪!

为什么会这样?

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

【问题讨论】:

    标签: postgresql typescript nestjs typeorm


    【解决方案1】:

    在 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 关系

    【讨论】:

      【解决方案2】:

      应该设置级联。以下是我的实体示例:

      @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;
      }
      

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

      【讨论】:

      • 你能在你的答案周围添加更多上下文吗?
      • 我添加了一个完整的例子
      • 对了,cascade让它递归删除保存,谢谢!
      猜你喜欢
      • 1970-01-01
      • 2021-11-11
      • 2020-04-06
      • 2021-03-08
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 2019-04-24
      相关资源
      最近更新 更多