最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - TypeOrm save method not updating object - Stack Overflow

programmeradmin2浏览0评论

Consider this entity:

// account.ts
import { Entity, PrimaryGeneratedColumn, PrimaryColumn, Column, BaseEntity, Index, CreateDateColumn,  UpdateDateColumn, OneToOne, JoinColumn } from 'typeorm'

@Entity()
export class Account extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ length: 50, unique: true })
  @Index({ unique: true })
  accountIdentifier: string

  @Column({ nullable: true, length: 100 })
  name?: string
}

To save a new account or return an existing account we have this working code:

const knownAccount = await Account.findOne({ accountIdentifier: token.oid })
if (knownAccount) return done(null, knownAccount, token)

const account = new Account()
account.accountIdentifier = token.oid
account.name = token.name
account.userName = (token as any).preferred_username
const newAccount = await account.save()
return done(null, newAccount, token)

In the docs it says:

save - Saves a given entity or array of entities. If the entity already exist in the database, it is updated. If the entity does not exist in the database, it is inserted. It saves all given entities in a single transaction (in the case of entity, manager is not transactional). Also supports partial updating since all undefined properties are skipped. Returns the saved entity/entities.

So we would expect this code to work and replace the previous code but it does not seem to update the row but rather complains about inserting a duplicate key:

const account = await Account.save({
   accountIdentifier = token.oid,
   name = token.name,
   userName = (token as any).preferred_username,
})
return done(null, account, token)

The IDE does show it will update or insert but it does not update:

How is it possible to use the save method correctly? So it adds an account if it doesn't exist and/or updates the account when it's already there.

Consider this entity:

// account.ts
import { Entity, PrimaryGeneratedColumn, PrimaryColumn, Column, BaseEntity, Index, CreateDateColumn,  UpdateDateColumn, OneToOne, JoinColumn } from 'typeorm'

@Entity()
export class Account extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ length: 50, unique: true })
  @Index({ unique: true })
  accountIdentifier: string

  @Column({ nullable: true, length: 100 })
  name?: string
}

To save a new account or return an existing account we have this working code:

const knownAccount = await Account.findOne({ accountIdentifier: token.oid })
if (knownAccount) return done(null, knownAccount, token)

const account = new Account()
account.accountIdentifier = token.oid
account.name = token.name
account.userName = (token as any).preferred_username
const newAccount = await account.save()
return done(null, newAccount, token)

In the docs it says:

save - Saves a given entity or array of entities. If the entity already exist in the database, it is updated. If the entity does not exist in the database, it is inserted. It saves all given entities in a single transaction (in the case of entity, manager is not transactional). Also supports partial updating since all undefined properties are skipped. Returns the saved entity/entities.

So we would expect this code to work and replace the previous code but it does not seem to update the row but rather complains about inserting a duplicate key:

const account = await Account.save({
   accountIdentifier = token.oid,
   name = token.name,
   userName = (token as any).preferred_username,
})
return done(null, account, token)

The IDE does show it will update or insert but it does not update:

How is it possible to use the save method correctly? So it adds an account if it doesn't exist and/or updates the account when it's already there.

Share Improve this question edited Aug 7, 2020 at 7:21 DarkLite1 asked Aug 7, 2020 at 7:09 DarkLite1DarkLite1 14.7k44 gold badges135 silver badges233 bronze badges 2
  • Hi, what fix you did for this?, I am using Entity manager.save under transaction, I too facing the same issue – Gobi Commented Jan 21, 2021 at 8:06
  • The workaround is first do .findOne() and then do .save() if it didn't' find an account. Example is the second code block in the question above. – DarkLite1 Commented Jan 21, 2021 at 9:15
Add a comment  | 

3 Answers 3

Reset to default 10

If it can help people who face the same problem, i think that .save() will perform an update in case the primary column (id in this case) is precised and exists in database. But be careful if the value of "id" is a string, i don't know why but somehow the save method won't perform the update, instead it will try to insert a new entity inside the database with the given id which may conduct to a constraint fail error (duplicate entry '' for key 'PRIMARY') if the id already exists, to avoid this simply typecast 'id' to integer.

When we use TypeORM .save for an update it compares the IDs to decide whether to send CREATE or UPDATE request to DB.

In my case, the IDs were '123ce' and '123CE', so TypeORM decides to CREATE a new record. DB responds that it's already exists.

The way out is check out how your DB stores IDs, and to use appropriate method for an ID. For instance, .toUpperCase():

accountIdentifier = token.oid.toUpperCase(),

I spend a while later but in case it helps someone: In my case I have this entity

export class orders {
     @AutoMap()
     @PrimaryColumn({ type: 'bigint' })
     id!: number;
}

When Typeorm tries to do the save() the format that the 'ID' field has in the table is of type string (the bigint type is saved as string type in the db), but the one that the entity has is of type interger, so it would be necessary for you to use another data type 'ID', cast it or in my case change the type to string:

export class orders {
     @AutoMap()
     @PrimaryColumn({ type: 'bigint' })
     id!: string;
}

That should work.

发布评论

评论列表(0)

  1. 暂无评论