TypeOrm 不会在更新时保存实体及其关系
Posted
技术标签:
【中文标题】TypeOrm 不会在更新时保存实体及其关系【英文标题】:TypeOrm doesn't save entity with it's relation on update 【发布时间】: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
实体的地址已更新,所以这真的很奇怪!
为什么会这样?
注意:所有查询都在一个事务中完成;我不知道这是否重要
【问题讨论】:
【参考方案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让它递归删除保存,谢谢!以上是关于TypeOrm 不会在更新时保存实体及其关系的主要内容,如果未能解决你的问题,请参考以下文章
TypeORM:保存时无法读取未定义的属性“inverseJoinColumns”
Typeorm - 无法更新实体,因为实体中未设置实体 ID