Typeorm 如何更新实体(如果存在)或创建实体(如果不存在)
这里是我的实体Typeorm 如何更新实体(如果存在)或创建实体(如果不存在),typeorm,Typeorm,这里是我的实体 // user @PrimaryGeneratedColumn() public id: number; @Column({ type: 'varchar', nullable: false }) public email: string; @Column({ type: 'varchar', nullable: false }) public password: string; @OneToOne(() => Token, (token: Token) =>
// user
@PrimaryGeneratedColumn()
public id: number;
@Column({ type: 'varchar', nullable: false })
public email: string;
@Column({ type: 'varchar', nullable: false })
public password: string;
@OneToOne(() => Token, (token: Token) => token.user)
public token: Token;
这就是我在数据库中保存当前数据的方式
private async savePayload(tokenDto: CreateTokenDto) {
const token = this.tokenRepository.create(tokenDto);
return await this.tokenRepository.save(token);
}
当我第一次将令牌保存到数据库时,所有令牌都被保存
当我第二次保存时,我得到一个错误
private async savePayload(tokenDto: CreateTokenDto) {
const a = {
// id: 15,
uuid: '343443443444444444444444',
userId: 36,
};
const token = this.tokenRepository.create(a);
return await this.tokenRepository.save(token);
}
ER_DUP_条目:键“REL_d417e5d35f2434afc4bd48cb4d”的重复条目“36”
我阅读了有关save方法的文档。但是为什么我会出错,我不明白。我希望记录会更新。为什么我的令牌详细信息没有更新
我了解如何使用sql实现这一点
INSERT INTO "Tokens" (UUID, USERID)
VALUES ('d93ab036-768c-420a-98d6-2f80c79e6ae7', 36)
ON CONFLICT (USERID)
DO UPDATE SET UUID = 'd93ab036-768c-420a-98d6-2f80c79e6ae7',
USERID = 36'
经过一些实验,我注意到当我指定令牌id时,保存或更新是成功的
private async savePayload(tokenDto: CreateTokenDto) {
const a = {
id: 15,
uuid: '343443443444444444444444',
userId: 36,
};
const token = this.tokenRepository.create(a);
return await this.tokenRepository.save(token);
}
但是如果我没有指明令牌的id,我会得到一个错误
private async savePayload(tokenDto: CreateTokenDto) {
const a = {
// id: 15,
uuid: '343443443444444444444444',
userId: 36,
};
const token = this.tokenRepository.create(a);
return await this.tokenRepository.save(token);
}
ER_DUP_条目:键“REL_d417e5d35f2434afc4bd48cb4d”的重复条目“36”
我搜索并找到了一些例子
一,
二,
他们说该值必须是主键或唯一值。但是我的userId字段是一个索引,也是唯一的
有哪些选项,为什么我的令牌没有更新?这并不是说表中已经有一个重复的条目,而是说已经有一个条目具有主键的该值,并且出于这个原因拒绝插入第二个条目 您将找到一个匹配的行,并且出现错误时的代码正试图插入第二行 在插入时处理重复项:
如果您尝试为主键或唯一索引插入重复的值,则始终会出现该错误。有两种解决方法:在插入之前检查,如果某些内容可能已更改,则进行更新,或者不执行任何操作。并不是说表中已经存在重复条目,这意味着其中已经有一个条目具有主键的该值,并且出于这个原因拒绝插入第二个条目 您将找到一个匹配的行,并且出现错误时的代码正试图插入第二行 在插入时处理重复项:
如果您尝试为主键或唯一索引插入重复的值,则始终会出现该错误。有两种解决方法:在插入之前进行检查,如果某些内容可能已更改,则执行更新,或者不执行任何操作。整个问题都是Repository.save函数行为的结果 根据,保存功能具有以下行为: 在数据库中保存所有给定的实体。如果数据库中不存在实体,则插入,否则更新 但是,如果实体中没有id字段(没有PrimaryKey),则save方法假定该实体在数据库中不存在,并继续创建一个新实体,而不是更新现有实体。这就是为什么在实体中定义id字段时它会起作用 考虑到这一点,保存方法似乎不适合您的情况。您需要使用TypeORM的查询生成器编写自定义查询。这个自定义查询将非常接近您在问题中使用原始SQL编写的查询 您可以这样编写免责声明:我根本没有测试过代码!: 常量值={ uuid:'34344344344444', 用户ID:36 } 等待连接。createQueryBuilder 插入 .代币 .valuespost2 .onConflict`userId DO更新集UUID=:UUID` .setParametertitle,values.uuid 处决 也许,您的另一个选择是使userId字段成为表的主键。这将通过save函数解决upsert问题。正如您所描述的,userId字段是一个索引,也是唯一的。因此,您可以轻松地将其作为主字段 这可以通过修改实体、删除@PrimaryGenerateId并将用户ID设置为@PrimaryColumn来实现: @列{type:'varchar',可为空:false} 公共uuid:string; @主柱 public userId:number; @OneToOne=>User,User:User=>User.hash,{cascade:['insert','remove']} @JoinColumn{name:'userId'} 公共用户:用户;
希望能有所帮助:整个问题都是Repository.save函数行为的结果 根据,保存功能具有以下行为: 在数据库中保存所有给定的实体。如果数据库中不存在实体,则插入,否则更新 但是,如果实体中没有id字段(没有PrimaryKey),则save方法假定该实体在数据库中不存在,并继续创建一个新实体,而不是更新现有实体。这就是为什么在实体中定义id字段时它会起作用 考虑到这一点,保存方法似乎不适合您的情况。您需要使用TypeORM的查询生成器编写自定义查询。这个自定义查询将非常接近您在问题中使用raw S编写的查询 QL 您可以这样编写免责声明:我根本没有测试过代码!: 常量值={ uuid:'34344344344444', 用户ID:36 } 等待连接。createQueryBuilder 插入 .代币 .valuespost2 .onConflict`userId DO更新集UUID=:UUID` .setParametertitle,values.uuid 处决 也许,您的另一个选择是使userId字段成为表的主键。这将通过save函数解决upsert问题。正如您所描述的,userId字段是一个索引,也是唯一的。因此,您可以轻松地将其作为主字段 这可以通过修改实体、删除@PrimaryGenerateId并将用户ID设置为@PrimaryColumn来实现: @列{type:'varchar',可为空:false} 公共uuid:string; @主柱 public userId:number; @OneToOne=>User,User:User=>User.hash,{cascade:['insert','remove']} @JoinColumn{name:'userId'} 公共用户:用户; 希望有帮助:您可以使用。保存更新和插入,或者检查是否存在。更新其他。保存 例 您可以同时使用.save进行更新和插入,或者检查是否存在.update else.save 例
是的,第二个选项与我预期的一样有效。这是最完整的答案。谢谢,第二个选项如我所料有效。这是最完整的答案。谢谢
async CreateNewRole(data: any): Promise<Role | any> {
try {
const entity = await this.roleRepository.create(data);
const role = await this.roleRepository.save(entity);
this.trackingService.create(data.user);
return {
success: true,
role,
};
} catch (e) {
// code == 23505 means duplication key
if (parseInt(e.code) === 23505) {
console.log('error : ', e.detail);
return {
success: false,
message: ROLE_ERROR_MESSAGES.ROLE_IS_FOUND,
};
} else {
return {
success: false,
};
}
}
}
async UpdateRole(data: any, id: number): Promise<Role | any> {
try {
await this.roleRepository.update(id, { ...data.payload });
this.trackingService.create(data.user);
// todo this need to be refactored !!
// return back the updated entity
const role = await this.roleRepository.find({ id });
console.log('role updated ', role);
return {
role,
success: true,
};
} catch (e) {
if (parseInt(e.code) === 23505) {
console.log('error : ', e.detail);
return {
success: false,
message: ROLE_ERROR_MESSAGES.ROLE_IS_FOUND,
};
} else {
return {
success: false,
};
}
}
}