NestJS结合TypeORM:捕获PostgreSQL save()时的unique_violation错误
数据库唯一约束冲突的处理实现
首先必须先在数据库的name字段上添加唯一约束——这是核心前提,只有数据库层面存在该约束,重复插入时才会触发unique_violation类型的错误,这比你用.some()全表遍历检查高效得多,还能避免并发场景下的竞态问题。
接下来完善你给出的代码逻辑,具体处理步骤如下:
- 捕获
QueryFailedError后,通过数据库特定的错误码判断是否为唯一约束冲突:- PostgreSQL:错误码是
23505 - MySQL:错误码是
1062 - SQLite:错误码是
SQLITE_CONSTRAINT_UNIQUE
- PostgreSQL:错误码是
- 确认是唯一约束冲突时,抛出业务友好的自定义错误;其他类型的数据库错误直接原样抛出,不做拦截。
完善后的代码示例(以PostgreSQL为例):
import { QueryFailedError } from '@nestjs/typeorm'; // 根据你使用的数据库替换对应的错误码 const UNIQUE_VIOLATION_CODE = '23505'; try { const newObject = await this.repository.save({ ...newObjectDto, }); return newObject; } catch (err) { if (err instanceof QueryFailedError) { // 校验是否为唯一约束冲突错误 if (err.driverError.code === UNIQUE_VIOLATION_CODE) { throw new Error('该名称已被占用,请更换其他名称'); } // 其他数据库操作错误,直接抛出原错误 throw err; } // 非数据库查询错误,原样抛出 throw err; }
关键提醒
- 不要仅依赖应用层检查:哪怕你在保存前用代码查一遍数据库,高并发场景下还是可能出现两个请求同时通过检查、最终插入重复数据的情况,只有数据库的唯一约束能彻底杜绝这种问题。
- 不同数据库的错误码差异:上面的示例用了PostgreSQL的错误码,如果你用的是其他数据库,一定要替换成对应数据库的唯一约束冲突错误码。
内容的提问来源于stack exchange,提问作者Szymon Kaszuba-Gałka
相关产品推荐
相关产品推荐

