TypeOrm:使用键的 uuid 数据类型而不是整数创建多对一关系

Posted

技术标签:

【中文标题】TypeOrm:使用键的 uuid 数据类型而不是整数创建多对一关系【英文标题】:TypeOrm: Create a ManyToOne relationship using uuid data type for the keys instead of integer 【发布时间】:2019-06-14 07:19:33 【问题描述】:

我有一个使用 TypeORM 和 PostgreSQL 数据库的 Typescript Nestjs 项目,但我无法定义多对一关系,因为 TypeORM 尝试创建整数类型的 ID 字段,而我使用的是 UUID 字段。有没有办法告诉 TypeORM 使用与整数不同的数据类型?

这是一个不工作的实体示例:

export class AgentKitsEntity implements Model 
  @PrimaryGeneratedColumn()
  @Generated('uuid')
  id: string;


@Entity(name: 'users')
export class User extends AgentKitsEntity implements UserModel 
  @Column()
  username: string;

  @ManyToOne(type => View)
  @JoinColumn(name: 'view_id', referencedColumnName: 'id')
  view: View;

这会导致以下错误:

query failed: ALTER TABLE "users" ADD CONSTRAINT "FK_2ed8b186dce83a446f94ac9aae4" FOREIGN KEY ("view_id") REFERENCES "views"("id")
error:  error: foreign key constraint "FK_2ed8b186dce83a446f94ac9aae4" cannot be implemented
    at Connection.parseE (/home/jonathan/projects/agent-kits/api-data/node_modules/pg/lib/connection.js:554:11)
    at Connection.parseMessage (/home/jonathan/projects/agent-kits/api-data/node_modules/pg/lib/connection.js:379:19)
    at Socket.<anonymous> (/home/jonathan/projects/agent-kits/api-data/node_modules/pg/lib/connection.js:119:22)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at Socket.Readable.push (_stream_readable.js:208:10)
    at TCP.onread (net.js:601:20)
  name: 'error',
  length: 228,
  severity: 'ERROR',
  code: '42804',
  detail: 'Key columns "view_id" and "id" are of incompatible types: integer and uuid.',
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'tablecmds.c',
  line: '6503',
  routine: 'ATAddForeignKeyConstraint' 

编辑:为了清楚起见,问题不在于为主键创建 UUID 字段,这是有效的。问题是我正在引用的表(在本例中为“views”)使用 UUID 主键,因此我还需要为引用它的字段使用 UUID(在本例中为“views”)。 TypeORM 自动创建具有整数类型的“view_id”字段,大概是因为它假定主键值将(应该?)总是整数(这让我觉得这是一个非常疯狂的假设)。

它必须是可配置的,不是吗?

【问题讨论】:

【参考方案1】:

我最终找到了解决方案,我将在此处发布以供将来参考。

以下对我有用:

export class AgentKitsEntity implements Model 
  @PrimaryGeneratedColumn('uuid')
  @Generated('uuid')
  id: string;


@Entity(name: 'users')
export class User extends AgentKitsEntity implements UserModel 

  @Column()
  username: string;

  @ManyToOne(type => View,  nullable: true )
  @JoinColumn(name: 'view_id')
  view: View;

似乎已经解决的关键区别是我在@PrimaryGeneratedColumn() 装饰器中指定了“uuid”。这令人惊讶,因为字段实际上是在数据库中正确创建为 UUID,但似乎 TypeORM 假定关键字段是整数,除非您明确指定类型,即使它知道如何创建正确的数据字段本身的类型。

编辑:仔细检查后发现@Generated('uuid') 实体是多余的,因此上面基类的代码可以简化为:

export class AgentKitsEntity implements Model 
  @PrimaryGeneratedColumn('uuid')
  id: string;

【讨论】:

以上是关于TypeOrm:使用键的 uuid 数据类型而不是整数创建多对一关系的主要内容,如果未能解决你的问题,请参考以下文章

TypeORM:更改主键长度后出现重复输入错误

UUID 与主键的自动递增数

带有 UUID 主键的 ActiveRecord 迁移

TypeORM 生成奇怪的“无版本”UUID

使用 C 类型 uuid_t 作为 std::map 中的键的最佳方法是啥?

vue-uuid 的 v-for 键的 uuid?