【问题标题】:How do you set a custom default unique id string for the @PrimaryGeneratedColumn in a TypeORM Entity?如何为 TypeORM 实体中的 @PrimaryGeneratedColumn 设置自定义默认唯一 ID 字符串?
【发布时间】:2019-02-08 23:39:02
【问题描述】:

我有一个用例需要在我的表中使用自定义字符串主键。 (我不想使用 GraphQL 提供的默认 'uuid',而是想使用 shortid library 来生成自定义唯一 ID。)

我是 TypeORM 初学者,我没有找到任何关于在文档中设置自定义默认主键的信息。是否可以在TypeORM PrimaryGeneratedColumn 中实现我想要的,还是我必须通过其他方式完成我想要的?

更新:我了解到我可以在保存实体之前使用 @BeforeInsert listener 修改实体,但 TypeORM 仍然不允许我覆盖 PrimaryGeneratedColumn('uuid') 并使用 shortId 字符串,因为 shortId 字符串不是有效的uuid。

【问题讨论】:

  • 根据您使用的数据库,指定@PrimaryGeneratedColumn('uuid')意味着数据库字段类型将为uuid,您不能在其中插入无效的UUID。我建议装饰如您所描述的,使用@PrimaryColumn('char', { length: <shortId length> }) 并使用@BeforeInsert 侦听器。这将为您提供 shortId 的固定长度字符主键。
  • 再次查看 shortId 文档,我注意到生成的 ID 可能是可变长度的;如果是这样,您将要使用@PrimaryColumn('varchar', { length: &lt;max-shortid-length&gt; }) 而不是上述...
  • @PrimaryColumn 正是我所需要的。我是个菜鸟,我什至不知道 PrimaryColumn 是一个装饰器:# 我的代码最终看起来像这样 @PrimaryColumn('varchar', { default: shortid.generate(), length: 14 }) 感谢您的帮助!我会投票支持你的 cmets,但它不会让我:/
  • 发布为答案,以便您投票!顺便说一句,带有default 选项的列,您是传递函数本身(即default: shortid.generate)还是调用它并默认为其返回值(default: shortid.generate())?除非我弄错了,否则您将需要前者 - 否则每次您的应用启动时,TypeORM 都会有一个默认值,并允许插入一条记录,但随后会因重复键违规而出错。
  • @Timshel 你是对的,我遇到了重复的密钥违规。但是,当我尝试您推荐的更改时,我一直遇到column "gz68lzqnmn" does not exist(id 每次都更改)错误。我发现解决此问题的唯一方法是保留default: shortid.generate(),但随后在BeforeInsert 挂钩中我添加了this.id = shortid.generate()。非常hacky和悲伤:(但它有效。如果你想进一步研究这个你可以拉这个repo和yarn start进行复制。不过没有压力。再次感谢!github.com/podverse/podverse-api/tree/primaryDefaultBug

标签: javascript entity typeorm


【解决方案1】:

@Timshel 的答案在使用 SQLite 时不起作用,因为默认值必须是常量。它给出了以下错误:

UnhandledPromiseRejectionWarning: QueryFailedError: SQLITE_ERROR: default value of column [id] is not constant

相反,您可以使用@BeforeInsert 来实现所需的结果,如下所示:

@Field(() => ID)
@PrimaryColumn("varchar", {
  length: 20
})
id: string;

@BeforeInsert()
setId() {
  this.id = shortid.generate();
}

【讨论】:

  • @Timshel 的回答也不适用于大多数其他驱动程序。我使用 MySQL 对其进行了测试,当我从我的实体创建迁移时,迁移包括:ALTER TABLE user CHANGE id id char(36) NOT NULL DEFAULT 177f7044-0805-4891-870e-8352cffa77bf。看起来如果您希望 TypeORM 进行值生成,您必须使用 @BeforeInsert
  • 出现其他问题,因为它要么无法更新实体,要么可能公开一种创建具有任意 ID 的实体的方法
  • 请注意,您必须将实体的实例(而不是普通对象)传递给save() 方法。
【解决方案2】:

如果数据库支持,@PrimaryGeneratedColumn('uuid') 装饰器会将列映射到 uuid 数据库字段类型,这意味着列值必须是有效的 UUID。

对于您的场景,我建议使用以下内容进行装饰: typescript @PrimaryColumn('varchar', { length: <max shortId length>, default: () => `'${shortid.generate()}'` })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    • 2021-08-01
    相关资源
    最近更新 更多