QueryFailedError:在表“graph”上插入或更新违反了外键约束“FK_0e40......”

Posted

技术标签:

【中文标题】QueryFailedError:在表“graph”上插入或更新违反了外键约束“FK_0e40......”【英文标题】:QueryFailedError: insert or update on table "graph" violates foreign key constraint "FK_0e40......" 【发布时间】:2020-06-28 19:11:00 【问题描述】:

我创建了一个非常小的reproduction repository。

请在下面查看我可能的解决方法。


我有一个图和一个图节点实体。图只知道它的起始图节点,而节点本身知道它属于哪个图及其后继图。

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

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

  @ManyToOne(() => GraphNode)
  @JoinColumn( name: "startNodeId" )
  public startNode?: GraphNode;


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

  @PrimaryColumn("uuid")
  public graphId: string;

  @ManyToOne(() => Graph,  onDelete: "CASCADE" )
  @JoinColumn( name: "graphId" )
  public graph: Graph;

  @Column( nullable: true )
  public successorGraphNodeId?: string;

  @ManyToOne(() => GraphNode)
  @JoinColumn( name: "successorGraphNodeId" )
  public successorGraphNode?: GraphNode;

如您所见,图表的 startnode 可能为空。此外,图形节点可能没有后继节点,因此该字段也可能为空。图节点具有复合主键很重要,因为它始终属于一个图。

我创建了一些非常基本的 CRUD 存储库操作来创建图形和图形节点。稍后我想更新该图的起始节点 ID。

图节点存储库只是创建了一个新实体

  public createGraphNode(graphId: string, successorGraphNodeId?: string): Promise<GraphNode> 
    const graphNode: GraphNode = new GraphNode();
    graphNode.graphId = graphId;
    graphNode.successorGraphNodeId = successorGraphNodeId;
    return graphNode.save();
  

图形存储库创建一个新实体并能够更新其起始节点 ID

  public createGraph(startNodeId?: string): Promise<Graph> 
    const graph: Graph = new Graph();
    graph.startNodeId = startNodeId;
    return graph.save();
  

  public updateStartNodeId(graphId: string, startNodeId: string): Promise<UpdateResult> 
    return this.update(graphId, 
      startNodeId
    );
  

在运行应用程序时,我会创建一个新图表。之后,我创建一个新的图形节点并将图形 ID 分配给它。此图节点没有后继节点。最后我将图节点指定为图开始节点。

const graph: Graph = await graphsRepository.createGraph();
const graphNode: GraphNode = await graphNodesRepository.createGraphNode(graph.id);
await graphsRepository.updateStartNodeId(graph.id, graphNode.id);

这样做我得到以下数据库错误

QueryFailedError: 在表“graph”上插入或更新违反了外部 关键约束“FK_0e4022833a9efc062c01637e552”

看来我的实体设计是错误的。有人知道怎么解决吗?

提前致谢


我可能会解决它

图形实体

通过referencedColumnName: "id"创建对PK的引用

@ManyToOne(() => GraphNode)
@JoinColumn( name: "startNodeId", referencedColumnName: "id" )
public startNode?: GraphNode;

图节点实体

对后继图节点执行相同操作

@ManyToOne(() => GraphNode)
@JoinColumn( name: "successorGraphNodeId", referencedColumnName: "id" )
public successorGraphNode?: GraphNode;

还将Unique 装饰器添加到实体并将id 字段标记为唯一

@Unique(["id"])

我唯一的问题是我不知道为什么要这样解决。

不知道为什么要通过referencedColumnName: "id"引用被引用表的PK,这个应该很明显了 我也不知道为什么我必须通过@Unique(["id"]) 将 id 列标记为唯一,因为该字段将始终是唯一的

【问题讨论】:

您是否尝试在 @OneToMany 属性中同时设置 onDelete: "CASCADE" 和 cascade: ["insert", "update", "remove" ]? @Aurinxki 这会有所作为吗?我专注于我在修复解决方案中提出的问题:) 【参考方案1】:

在您的 .Save() 中将 id 作为参数传递,否则它会认为您正在创建新数据。

【讨论】:

以上是关于QueryFailedError:在表“graph”上插入或更新违反了外键约束“FK_0e40......”的主要内容,如果未能解决你的问题,请参考以下文章

在 TypeORM 上接收“QueryFailedError:重复键值违反唯一约束”“pg_type_typname_nsp_index”错误

加入与子查询

Google BigQuery 的 SQL 语法不存在

Google BigQuery 中的 TIMESTAMP 和标准 SQL

openfalcon源码分析之graph

Graph I - Graph