返回

双向多对多关系在 TypeORM 中的处理与常见问题解答

javascript

在 TypeORM 中处理双向多对多关系

在 TypeORM 中,处理具有自引用多对多关系的表时,查询可能会遇到障碍。当关系被定义为只能从一个方向查询相关实体时,可能会出现这种情况。

问题解析

例如,考虑以下关系定义:

@ManyToMany((type) => TagEntity, { cascade: false })
@JoinTable({
    name: 'tags_tags_relation',
    joinColumn: { name: 'tag_id_1', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'tag_id_2', referencedColumnName: 'id' },
})
relatedTo: TagEntity[];

此定义只允许从 tag_id_1 列中查询给定标签 ID 关联的标签。

解决方案:双向查询

为了解决这个问题,我们需要修改关系定义以启用双向查询。我们可以利用 JoinTable 中的 inverseJoinColumns 选项:

@ManyToMany((type) => TagEntity, { cascade: false })
@JoinTable({
    name: 'tags_tags_relation',
    joinColumn: { name: 'tag_id_1', referencedColumnName: 'id' },
    inverseJoinColumns: [{ name: 'tag_id_2', referencedColumnName: 'id' }],
})
relatedTo: TagEntity[];

添加 inverseJoinColumns 选项后,TypeORM 将生成两个连接表之间的列,实现双向查询。

示例查询

修改后的关系定义允许使用以下查询:

const HVAC = AppDataSource.manager.findOne(TagEntity, {
          where: { name: 'HVAC' },
          relations: { relatedTo: true },
        }
// ==> HVAC.relatedTo will have 2 tag entities

const plumber = AppDataSource.manager.findOne(TagEntity, {
          where: { name: 'Plumber' },
          relations: { relatedTo: true },
        }
// ==> plumber.relatedTo will have 1 tag entity

现在,HVACplumber 实体都将具有关联的 relatedTo 实体。

结论

通过修改 JoinTable 选项,我们可以让 TypeORM 中的自引用多对多关系实现双向查询。这允许我们更灵活、全面地检索相关实体。

常见问题解答

  1. 如何识别只能单向查询的关系?
    • 检查 JoinTable 选项中是否存在 inverseJoinColumns。如果不存在,则关系只能单向查询。
  2. 为什么需要双向查询?
    • 双向查询使我们可以更灵活地从任何方向检索相关实体。
  3. inverseJoinColumns 选项有什么作用?
    • inverseJoinColumns 选项生成连接表之间用于双向查询的列。
  4. 除了使用 inverseJoinColumns 之外,还有其他方法实现双向查询吗?
    • 没有。inverseJoinColumns 是 TypeORM 中实现双向查询的唯一方法。
  5. 修改关系定义后是否需要重新生成数据库架构?
    • 如果更改了 JoinTable 选项,则需要重新生成数据库架构。