跳至主内容区

关系操作

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

RelationQueryBuilder 是一种特殊类型的 QueryBuilder,用于处理实体关系。 通过它,您可以直接在数据库中绑定实体间的关联关系,无需加载任何实体对象, 也可以轻松加载关联实体。

例如,我们有一个 Post 实体,它与 Category 实体存在名为 categories 的多对多关系。 现在我们向这个多对多关系中添加新分类:

await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post)
.add(category)

这段代码等效于:

const postRepository = dataSource.manager.getRepository(Post)
const post = await postRepository.findOne({
where: {
id: 1,
},
relations: {
categories: true,
},
})
post.categories.push(category)
await postRepository.save(post)

但前者效率更高,因为它只需最少量的数据库操作即可完成实体绑定, 避免了调用臃肿的 save 方法。

这种方法的另一优势是:您无需预先加载所有关联实体再进行添加操作。 例如,当单个文章关联了上万种分类时,向列表添加新分类会成为性能瓶颈—— 常规做法需要先加载包含全部分类的文章实体,添加新分类后再保存。 这会产生巨大的性能开销,在生产环境中基本不可行。 而使用 RelationQueryBuilder 能完美解决此问题。

实际上在"绑定"操作时甚至不需要实体对象,直接使用实体 ID 即可。 例如将 ID=3 的分类添加到 ID=1 的文章中:

await dataSource.createQueryBuilder().relation(Post, "categories").of(1).add(3)

若使用复合主键,则需传入 ID 映射对象:

await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of({ firstPostId: 1, secondPostId: 3 })
.add({ firstCategoryId: 2, secondCategoryId: 4 })

移除实体的操作方式与添加相同:

// this code removes a category from a given post
await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.remove(category) // you can use just category id as well

添加/移除关联实体的操作适用于 many-to-manyone-to-many 关系。 对于 one-to-onemany-to-one 关系,请改用 set 方法:

// this code sets category of a given post
await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.set(category) // you can use just category id as well

若要解除关联(设为 null),只需向 set 方法传入 null

// this code unsets category of a given post
await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.set(null)

除更新关系外,关系查询构建器还支持加载关联实体。 例如在 Post 实体中存在多对多的 categories 关系和多对一的 user 关系, 可通过以下代码加载这些关联:

const post = await dataSource.manager.findOneBy(Post, {
id: 1,
})

post.categories = await dataSource
.createQueryBuilder()
.relation(Post, "categories")
.of(post) // you can use just post id as well
.loadMany()

post.author = await dataSource
.createQueryBuilder()
.relation(Post, "user")
.of(post) // you can use just post id as well
.loadOne()