TypeORM - 重复键值违规

Vac*_*cek 4 orm typeorm nestjs

假设我有一个像这样的简单 TypeORM 实体:

import { Entity, PrimaryGeneratorColumn, Column } from 'typeorm';

@Entity()
export class Employee {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    Name: string;
}
Run Code Online (Sandbox Code Playgroud)

只要我不手动接触数据库,一切都可以正常工作。如果我手动输入记录,实体将无法检查id表中的最后一个当前记录并抛出 error duplicate key value violates unique constraint

例如:

  1. Employee Entity自己创建两条记录。
  2. 我的数据库中有两条记录,最后一条记录有id 2
  3. 我在数据库中手动创建第三条记录,它有id 3
  4. 之后,当Employee Entity运行时,它不会 = 创建另一个记录,因为它想使用id 3,但我已经手动添加了。
  5. 我收到错误duplicate key value violates unique constraint
  6. Employee Entity再次运行时,它会起作用,因为它尝试在已经可用的情况下保存另一条记录id 4

那么我如何确保检查Employee Entity数据库中的最后一个 id,然后使用增量保存下一条记录id

谢谢

小智 5

在 TypeORM 中,装饰器@PrimaryGeneratedColumn()创建一个主列,该列的值将使用序列生成。每次在数据库中添加新记录时,它都会使用nextval该列的序列集。假设您正在使用 PostgreSQL(我相信其他数据库也会类似),您有一个 Employee 表

CREATE TABLE public.Employee (
    number serial NOT NULL,
    nane varchar NULL
);
Run Code Online (Sandbox Code Playgroud)

并且因为装饰器也会创建@PrimaryGeneratedColumn()一个序列。employee_id_seq您可以通过运行来检查其最新值

select last_value from employee_id_seq; 
Run Code Online (Sandbox Code Playgroud)

当您的应用程序创建两条记录时,它会使用该序列生成新的 id,从而更改值employee_id_seq last_value。数据库中有两条记录,新的 last_value 将更新为 2。

如果您手动创建第三条记录并传递 id = 3

INSERT INTO public.Employee (id, name) VALUES(3, 'new_name')
Run Code Online (Sandbox Code Playgroud)

该序列将不会被使用,并且它的last_value将为2。下次应用程序尝试插入新记录时,它会执行插入而不传递id,因为它依赖于序列来生成值,如下所示

INSERT INTO public.Employee (name) VALUES('another_name');
Run Code Online (Sandbox Code Playgroud)

或者(不确定 TypeORM 是如何准确处理它的)

INSERT INTO public.Employee (id, name) VALUES(nextval('employee_id_seq', 'another_name')
Run Code Online (Sandbox Code Playgroud)

上面的 SQL 将使用last_value序列中的 并添加 1,得到 3 和 a duplicate key violation。因此,如果您手动添加记录,则无需手动设置 id,您可以运行

INSERT INTO public.Employee (name) VALUES('name') 
Run Code Online (Sandbox Code Playgroud)

并且 id 将使用序列自动生成。