web-dev-qa-db-ja.com

外部キー制約»FK_0e4022833a9efc062c01637e552«を実装できません-複合主キーに問題がありますか?

TypeORMを使用していて、現在3つのエンティティでデータベースを設計したいと考えています。複製用のリポジトリを作成しました

Github複製リポジトリー

更新

2つの小さな実体でそれを再現することができました

非常に小さな複製リポジトリ

これについての詳細は以下をご覧ください


つまり、まず最初にmoduleエンティティを作成します。これはいくつかの基本的なフィールドのみを格納するため、小さなものです。

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

  // some other fields without references
}

次にgraphエンティティがあります。これは複数のgraphNodesを保持しています。したがって、複数のグラフを作成でき、それぞれに独自のgraphNodeがあります。グラフ自体は、どのgraphNodeがグラフの最初のものかを知る必要があります。そこで、graphNodeエンティティへの外部キー参照を設定しようとしました。

  • 複数のグラフが存在する可能性があります
  • 各グラフには開始ノードとして1つのgraphNodeがあります
  • グラフごとに複数のgraphNodesがあります

@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;
}

最後のエンティティはgraphNodesエンティティです。各graphNodeは、1つのグラフ内のモジュールを表します。また、その後継者successGraphNodeIdおよびerrorGraphNodeIdについても認識します。ノードに重要なのは、このエンティティに複合主キーがあることです。これは、graphNodeをフェッチしたい場合は、グラフIDも渡す必要があるためです。基本的にこれらはユースケースです

  • graphNodeは1つのモジュールを表します
  • グラフごとに複数のgraphNodesがあります
  • graphNodeはそれ自体を後続として参照できます(成功/エラー)
  • graphNodeサクセサーはnullにすることができます(成功/エラー)
  • graphNode後続は、thisグラフにすでに存在する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;
}

アプリケーションを実行すると、残念ながらこのエラーが発生します

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)

エンティティのデザインが正しくないようです。誰かがここで何が間違っているか何が欠けているか知っていますか?さらに情報が必要な場合や、複製リポジトリを更新する必要がある場合は、お知らせください。

前もって感謝します


更新

2つの小さな実体でそれを再現することができました。グラフには関係しかない

@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;
}

とそのノード

@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;
}

前述のように、問題は複合主キーに依存しているようです。ノードのgraphIdプライマリ列を基本的な列に変換したくないのは、データベースの設計が悪いためです...

5
hrp8sfH4xQ4

エンティティで外部キー制約を次のように使用しています。

@ManyToOne(
    () => GraphNode,
    graphNode => graphNode.id,
)

と他のエンティティでそれぞれ。現在のデータベースがこのルールを満たしていないため、エラーが発生しています。したがって、これを機能させる最も簡単な方法は次のとおりです。

  1. 現在のデータベースを削除
  2. 新しいデータベースを作成する
  3. 新しく作成したデータベースに接続するように構成を変更します。

これを行うと、新しく作成されたすべてのレコードがデータベースの更新された制約に従って動作します。これがうまくいくことを願っています。

0