【发布时间】: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 这会有所作为吗?我专注于我在修复解决方案中提出的问题:)
标签: postgresql nestjs typeorm