Reputation: 1201
Given the following 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;
}
And the addres relation:
@Entity({name: 'addresses'})
export class Address {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({length: 45})
country: string;
}
When I get the account
entity by this:
/**
* 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']});
}
I get the full Account
entity with the Address
relation in it.
And then when I do the following:
account.address.country = 'newcountry';
and do this.save(account)
in accountRepository
the address won't update at all!
When I do console log before the save, I see the account
entity with the updated address, so this is something really strange!
Why is it happening?
Note: All queries are done in a transaction; I dont know if it matters
Upvotes: 5
Views: 20883
Reputation: 2817
The cascade should be set. Here is an example of mine entities:
@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;
}
This should also work for onetoone relation as well.
Upvotes: 2
Reputation: 533
Doing that kind of update on sql is quite complicated and even with queryBuilder TypeORM doesn't support join updates (you can see it here). The relation selector is quite helpfull but I would advise you to use it when its really necesary and add a nullable field to get the Ids of the address and obtain the address on separate it makes the things a lot easier in cases you need to change that relation lets say when you want to change the whole address object. this would be the result in the relations:
@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;
}
And you can keep calling the relation as you did before with:
public async getAccountByAccountIdWithRelations(accountId: string): Promise<Account> {
return await this.findOneOrFail({id: accountId}, {relations: ['address']});
}
Using this aproach would keep inserting and updating easy and it works also in the oneToMany => manyToOne Relations too
Upvotes: 0