如何在 TypeORM 中使用具有自动递增 id 列的表进行级联插入

Posted

技术标签:

【中文标题】如何在 TypeORM 中使用具有自动递增 id 列的表进行级联插入【英文标题】:How to do cascading inserts with tables having auto increment id columns in TypeORM 【发布时间】:2018-07-05 08:23:53 【问题描述】:

我正在尝试使用typeorm 实现级联插入。子表条目包括对父表上 ID 字段的外键引用。

似乎typeorm 没有从父行捕获自动增量id 并将其提供给子inserts。

这是父实体:

import ...
@Entity("parent")
export class Parent 
    @PrimaryGeneratedColumn()
    id: number;

    @OneToOne(type => Account, accountId => accountId.provider)
    @JoinColumn(name: "account_id")
    accountId: Account;

    @Column("varchar", 
        name: "name",
        nullable: false,
        length: 255,
    )
    name: string;

    @OneToMany(type => Child, Children => Children.parentId, 
        cascadeInsert: true,
        cascadeUpdate: true
    )
    Children: Child[];


和子实体:

import ...

@Entity("child")
export class Child
    @PrimaryGeneratedColumn()
    id: number;

    @ManyToOne(type => Parent, parentId => parentId.children)
    @JoinColumn(name: "parent_id")
    parentId: Parent;

    @Column("varchar", 
        name: "number",
        nullable: true,
        length: 45,
    )
    number: string;


控制台日志显示生成的sql不包含外键列,产生明显错误ER_NO_DEFAULT_FOR_FIELD: Field 'parent_id' doesn't have a default value

info: executing query:  START TRANSACTION
info: executing query:  INSERT INTO parent(name, account_id) VALUES (?,?) -- PARAMETERS: ["Name","id"]
info: executing query:  INSERT INTO child(number) VALUES (?) -- PARAMETERS: ["12345678"]
info: query failed:  INSERT INTO child(number) VALUES (?) -- PARAMETERS: ["12345678"]
info: error:   Error: ER_NO_DEFAULT_FOR_FIELD: Field 'parent_id' doesn't have a default value

是否可以指示 typeorm 捕获 LAST_INSERT_ID() 或以其他方式填充子行上的外键 id 字段?

【问题讨论】:

【参考方案1】:

如果 id 不是自动生成的,而是在保存实体之前分配的,它可以工作。

使用 uuid 作为主键。

import ...
@Entity("parent")
export class Parent 

    @PrimaryColumn()
    id: string;

    @OneToOne(type => Account, accountId => accountId.provider)
    @JoinColumn(name: "account_id")
    accountId: Account;

    @Column("varchar", 
        name: "name",
        nullable: false,
        length: 255,
    )
    name: string;

    @OneToMany(type => Child, Children => Children.parentId, 
        cascadeInsert: true,
        cascadeUpdate: true
   )
   Children: Child[];

以及创建实体时。

const parent: Parent = new Parent();
parent.id = "896b677f-fb14-11e0-b14d-d11ca798dbac"; // your uuid goes here

很遗憾,您也不能使用@PrimaryGeneratedColumn("uuid")

有很多库可以在 JS 中生成 uuid。

uuid-js 示例 - https://github.com/pnegri/uuid-js

const parent: Parent = new Parent();
parent.id = UUID.create(4).toString();

我认为这更像是一种解决方法,而不是问题的解决方案。但是我找不到一种方法来告诉 TypeORM 在级联子级时考虑生成的 id。

【讨论】:

以上是关于如何在 TypeORM 中使用具有自动递增 id 列的表进行级联插入的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ServiceStack OrmLite 中检索自动递增的 ID?

Java/Spring Boot Web 应用程序。插入具有自动递增 id 列的新行

在mysql中获取自动递增行ID的时间复杂度

首先使用代码禁用整数主键上的标识(自动递增)

添加具有自动递增的自定义 ID 的子项 - Firebase

sqlite:具有自动递增列的多列主键