无法在 typeorm 中使用 closure-table 创建树
Unable to make tree with closure-table in typeorm
我目前正在做一个项目,我的数据库中需要一棵树。对我来说,closure-table 是最好的选择,因为我会在某些时候需要图中的多个根。
我正在使用 typeorm 0.2.45,因为 nestJs 还不支持 0.3.*。
向数据库中添加实体时,没有链接,没有问题:
// ./entity/Node.ts
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, Tree, PrimaryColumn, TreeParent, TreeChildren } from "typeorm"
@Entity()
@Tree("closure-table")
export class Node extends BaseEntity {
@PrimaryColumn()
name: string
@TreeParent()
parent: Node
@TreeChildren()
children: Node[]
}
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"
AppDataSource.connect().then(async (conn) => {
const rNode = conn.getTreeRepository(Node)
await rNode.createQueryBuilder().delete().execute()
const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
await rNode.insert({name})
return rNode.findOne(name)
}))
console.log(await rNode.findTrees())
}).catch(error => console.log(error))
产量
[
Node { name: 'root', children: [] },
Node { name: 'child', children: [] }
]
但是当我尝试在树中添加关系时,一切都变糟了..
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"
AppDataSource.connect().then(async (conn) => {
const rNode = conn.getTreeRepository(Node)
await rNode.createQueryBuilder().delete().execute()
const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
await rNode.insert({name})
return rNode.findOne(name)
}))
child.parent = root;
await rNode.save(child);
console.log(await rNode.findTrees())
}).catch(error => console.log(error))
产量
[ Node { name: 'root', children: [] } ]
并且 table node_closure
完全是空的(请注意,当正确填充它时,我确实会出现树)。
我做错了什么?
谢谢
找到了答案,实际上似乎使用repository.insert
没有正确更新闭包table(应该包含恒等关系)。
由于身份不存在,因此无法在更改父级时传播它。
更正后的代码是
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"
AppDataSource.connect().then(async (conn) => {
const rNode = conn.getTreeRepository(Node)
await rNode.createQueryBuilder().delete().execute()
const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
await rNode.save({name})
return rNode.findOne(name)
}))
child.parent = root;
await rNode.save(child);
console.log(await rNode.findTrees())
}).catch(error => console.log(error))
不过要小心,因为保存等同于更新插入,如果找到具有相同主键的实体,则可以并且将会更新实体。
我目前正在做一个项目,我的数据库中需要一棵树。对我来说,closure-table 是最好的选择,因为我会在某些时候需要图中的多个根。
我正在使用 typeorm 0.2.45,因为 nestJs 还不支持 0.3.*。
向数据库中添加实体时,没有链接,没有问题:
// ./entity/Node.ts
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, Tree, PrimaryColumn, TreeParent, TreeChildren } from "typeorm"
@Entity()
@Tree("closure-table")
export class Node extends BaseEntity {
@PrimaryColumn()
name: string
@TreeParent()
parent: Node
@TreeChildren()
children: Node[]
}
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"
AppDataSource.connect().then(async (conn) => {
const rNode = conn.getTreeRepository(Node)
await rNode.createQueryBuilder().delete().execute()
const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
await rNode.insert({name})
return rNode.findOne(name)
}))
console.log(await rNode.findTrees())
}).catch(error => console.log(error))
产量
[
Node { name: 'root', children: [] },
Node { name: 'child', children: [] }
]
但是当我尝试在树中添加关系时,一切都变糟了..
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"
AppDataSource.connect().then(async (conn) => {
const rNode = conn.getTreeRepository(Node)
await rNode.createQueryBuilder().delete().execute()
const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
await rNode.insert({name})
return rNode.findOne(name)
}))
child.parent = root;
await rNode.save(child);
console.log(await rNode.findTrees())
}).catch(error => console.log(error))
产量
[ Node { name: 'root', children: [] } ]
并且 table node_closure
完全是空的(请注意,当正确填充它时,我确实会出现树)。
我做错了什么?
谢谢
找到了答案,实际上似乎使用repository.insert
没有正确更新闭包table(应该包含恒等关系)。
由于身份不存在,因此无法在更改父级时传播它。
更正后的代码是
import { AppDataSource } from "./data-source"
import { Node } from "./entity/Node"
AppDataSource.connect().then(async (conn) => {
const rNode = conn.getTreeRepository(Node)
await rNode.createQueryBuilder().delete().execute()
const [root, child] = await Promise.all(['root', 'child'].map(async (name) => {
await rNode.save({name})
return rNode.findOne(name)
}))
child.parent = root;
await rNode.save(child);
console.log(await rNode.findTrees())
}).catch(error => console.log(error))
不过要小心,因为保存等同于更新插入,如果找到具有相同主键的实体,则可以并且将会更新实体。