Skip to content

Has Many 关联

介绍

Has Many 关联表示一个模型拥有另一个模型的多个实例。这是一种一对多的关联关系,常用于表示父子关系或分类关系。

定义 Has Many 关联

使用 @HasMany 装饰器来定义一对多关联:

ts
import { Table, Field, FieldType, Model, HasMany, BelongsTo } from '@ibestservices/ibest-orm';

@Table({ name: 'users' })
class User extends Model {
  @Field({ type: FieldType.TEXT, tag: ['notNull'] })
  name?: string;

  @Field({ type: FieldType.TEXT })
  email?: string;

  @HasMany({
    target: () => Article,
    foreignKey: 'author_id',
    localKey: 'id'
  })
  articles?: Article[];

  constructor(name: string, email: string) {
    super();
    this.name = name;
    this.email = email;
  }
}

@Table({ name: 'articles' })
class Article extends Model {
  @Field({ type: FieldType.TEXT, tag: ['notNull'] })
  title?: string;

  @Field({ type: FieldType.TEXT })
  content?: string;

  @Field({ type: FieldType.INTEGER, tag: ['notNull'] })
  author_id?: number;

  @BelongsTo({
    target: () => User,
    foreignKey: 'author_id',
    localKey: 'id'
  })
  author?: User;

  constructor(title: string, content: string, author_id: number) {
    super();
    this.title = title;
    this.content = content;
    this.author_id = author_id;
  }
}

配置参数

target

  • 类型: () => Class
  • 描述: 目标模型类的工厂函数
  • 必需: 是

foreignKey

  • 类型: string
  • 描述: 目标表中的外键字段名
  • 默认值: ${当前表名}_id
  • 示例: 'author_id'

localKey

  • 类型: string
  • 描述: 当前表中的本地键字段名(通常是主键)
  • 默认值: 'id'
  • 示例: 'id'

cascade

  • 类型: CascadeType[]
  • 描述: 级联操作类型
  • 可选值: [CascadeType.Delete]
  • 示例: 删除用户时自动删除其所有文章

查询 Has Many 关联

预加载关联数据

ts
// 查询用户及其所有文章
const userWithArticles = await this.orm.Session(User)
  .With('articles')
  .Where('id', 1)
  .FirstWithRelations();

console.log('用户及文章:', userWithArticles);
// 输出:
// {
//   id: 1,
//   name: "张三",
//   email: "zhangsan@example.com",
//   articles: [
//     {
//       id: 1,
//       title: "TypeScript入门指南",
//       content: "TypeScript是JavaScript的超集...",
//       author_id: 1
//     },
//     {
//       id: 2,
//       title: "React最佳实践",
//       content: "React开发中的一些最佳实践...",
//       author_id: 1
//     }
//   ]
// }

查询多个用户的文章

ts
// 查询所有用户及其文章
const usersWithArticles = await this.orm.Session(User)
  .With('articles')
  .FindWithRelations();

usersWithArticles.forEach(user => {
  console.log(`用户 ${user.name} 共有 ${user.articles?.length || 0} 篇文章`);
});

嵌套预加载

ts
// 查询用户、文章及文章的评论
const userWithNestedData = await this.orm.Session(User)
  .With('articles.comments')
  .Where('id', 1)
  .FirstWithRelations();

注意事项

提示

  • Has Many 关联返回数组,即使没有关联数据也会返回空数组 []
  • 预加载查询会执行两次 SQL:先查主表,再查关联表
  • 使用级联删除时要谨慎,确保业务逻辑正确

注意

  • 大量关联数据可能影响查询性能
  • 删除主记录前要考虑关联数据的处理策略