外键约束 »FK_0e4022833a9efc062c01637e552« 无法实现 - 复合主键有问题?

hrp*_*xQ4 5 sql postgresql typeorm

我正在使用 TypeORM 并希望用当前的三个实体设计我的数据库。我创建了一个用于复制的存储库

Github 复制库

更新

我只能用两个小实体来复制它

非常小的复制回购

下面的更多信息


所以首先我有一个模块实体。这个很小,因为它只存储一些基本字段。

@Entity()
export class Module extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  public id: string;

  // some other fields without references
}
Run Code Online (Sandbox Code Playgroud)

接下来我有一个图形实体。这个持有多个graphNodes。所以你可以有多个图,每个图都有自己的图节点。图本身需要知道哪个 graphNode 是图中的第一个。所以我尝试设置对 graphNode 实体的外键引用。

  • 可以有多个图形
  • 每个图都有一个 graphNode 作为起始节点
  • 每个图有多个图节点

.

@Entity()
export class Graph extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  public id: string;

  @Column({ nullable: true })
  public startNodeId?: string;

  @ManyToOne(
    () => GraphNode,
    graphNode => graphNode.id,
  )
  @JoinColumn({ name: 'startNodeId' })
  public startNode: GraphNode;
}
Run Code Online (Sandbox Code Playgroud)

最后一个实体是graphNodes实体。每个 graphNode 代表一个图中的一个模块。它还知道它的后继者successGraphNodeIderrorGraphNodeId。节点这个实体有一个复合主键很重要,因为如果你想获取一个 graphNode,你也必须传入图 id。基本上这些是用例

  • 一个 graphNode 代表一个模块
  • 每个图有多个图节点
  • graphNode 可以将自身作为后继(成功/错误)
  • graphNode 后继者可以为空(成功/错误)
  • graphNode 后继者必须是图中已存在的 graphNode

.

@Entity()
export class GraphNode extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  public id: string;

  @PrimaryColumn()
  public graphId: string; // composite key https://github.com/typeorm/typeorm/blob/master/sample/sample27-composite-primary-keys/entity/Post.ts

  @ManyToOne(
    () => Graph,
    graph => graph.id,
  )
  @JoinColumn({ name: 'graphId' })
  public graph: Graph;

  @Column()
  public moduleId: string;

  @ManyToOne(
    () => Module,
    module => module.id,
  )
  @JoinColumn({ name: 'moduleId' })
  public module: Module;

  @Column({ nullable: true })
  public successGraphNodeId?: string;

  @ManyToOne(
    () => GraphNode,
    graphNode => graphNode.id,
  )
  @JoinColumn({ name: 'successGraphNodeId' })
  public successGraphNode?: GraphNode;

  @Column({ nullable: true })
  public errorGraphNodeId?: string;

  @ManyToOne(
    () => GraphNode,
    graphNode => graphNode.id,
  )
  @JoinColumn({ name: 'errorGraphNodeId' })
  public errorGraphNode?: GraphNode;
}
Run Code Online (Sandbox Code Playgroud)

运行应用程序时,我不幸收到此错误

QueryFailedError: Foreign key constraint »FK_0e4022833a9efc062c01637e552« cannot be implemented
    at new QueryFailedError (...\references-reproduction\node_modules\typeorm\error\QueryFailedError.js:11:28)
    at Query.callback (...\references-reproduction\node_modules\typeorm\driver\postgres\PostgresQueryRunner.js:176:38)
    at Query.handleError (...\references-reproduction\node_modules\pg\lib\query.js:145:17)
    at Connection.connectedErrorMessageHandler (...\references-reproduction\node_modules\pg\lib\client.js:214:17)
    at Connection.emit (events.js:223:5)
    at Socket.<anonymous> (...\references-reproduction\node_modules\pg\lib\connection.js:134:12)
    at Socket.emit (events.js:223:5)
    at addChunk (_stream_readable.js:309:12)
    at readableAddChunk (_stream_readable.js:290:11)
    at Socket.Readable.push (_stream_readable.js:224:10)
Run Code Online (Sandbox Code Playgroud)

看来我的实体设计不正确。有人知道这里出了什么问题或遗漏了吗?如果您需要更多信息或者我是否应该更新我的复制存储库,请告诉我。

提前致谢


更新

我能够用两个小实体重现它。图之间只有关系

@Entity()
export class Graph extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  public id: string;

  @Column({ nullable: true })
  public startNodeId?: string;

  @ManyToOne(
    () => Node,
    node => node.id,
  )
  @JoinColumn({ name: 'startNodeId' })
  public node: Node;
}
Run Code Online (Sandbox Code Playgroud)

及其节点

@Entity()
export class Node extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  public id: string;

  @PrimaryColumn()
  public graphId: string;

  @ManyToOne(
    () => Graph,
    graph => graph.id,
  )
  @JoinColumn({ name: 'graphId' })
  public graph: Graph;
}
Run Code Online (Sandbox Code Playgroud)

如前所述,问题似乎依赖于复合主键。我不想将节点的 graphId 主列转换为基本列,因为这将是糟糕的数据库设计...