postgresql - TypeOrm sparar inte entitet med dess relation vid uppdatering
Givet följande relation:
@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;
}
Och adressrelationen:
@Entity({name: 'addresses'})
export class Address {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({length: 45})
country: string;
}
När jag hämtar account-entiteten på detta sätt:
/**
* 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']});
}
Jag får hela Account-entiteten med Address-relationen i den.
Och sedan när jag gör följande:
account.address.country = 'newcountry';
och gör this.save(account) i accountRepository adressen kommer inte att uppdateras alls!
När jag gör en console log innan sparandet, ser jag account-entiteten med den uppdaterade adressen, så detta är verkligen något konstigt!
Varför händer det?
Obs: Alla frågor görs i en transaktion; jag vet inte om det spelar någon roll
Svar #1
Kaskaden ska vara inställd. Här är ett exempel på mina enheter:
@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;
}
Detta borde också fungera för en-till-en-relationer.
Svar #2
Att göra den typen av uppdatering på SQL är ganska komplicerat och även med queryBuilder stöder inte TypeORM join-uppdateringar (du kan se det här). Relationsväljaren är ganska hjälpsam men jag skulle råda dig att använda den när det verkligen är nödvändigt och lägga till ett nullable-fält för att få Id på adressen och hämta adressen separat, det gör saker mycket enklare i fall du behöver ändra den relationen, låt säga när du vill ändra hela adressobjektet. Detta skulle vara resultatet i relationerna:
@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;
}
Och du kan fortsätta kalla relationen som du gjorde tidigare med:
public async getAccountByAccountIdWithRelations(accountId: string): Promise<Account> {
return await this.findOneOrFail({id: accountId}, {relations: ['address']});
}
Att använda detta tillvägagångssätt skulle hålla infogning och uppdatering enkel och det fungerar även i oneToMany => manyToOne-relationer
