Skip to content

Has One 关联

介绍

Has One 关联表示一个模型拥有另一个模型的单个实例。这是一种一对一的关联关系,通常用于将一个表的数据扩展到另一个表中。

定义 Has One 关联

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

ts
import { Table, Column, PrimaryKey, HasOne, BelongsTo, ColumnType } from '@ibestservices/ibest-orm';

@Table()
class User {
  @PrimaryKey()
  id?: number;

  @Column()
  name!: string;

  @Column()
  email?: string;

  // 一对一关联:用户有一个档案
  @HasOne(() => UserProfile, { foreignKey: 'user_id' })
  profile?: UserProfile;
}

@Table({ name: 'user_profiles' })
class UserProfile {
  @PrimaryKey()
  id?: number;

  @Column({ name: 'user_id', type: ColumnType.INTEGER })
  userId?: number;

  @Column()
  avatar?: string;

  @Column()
  bio?: string;

  // 反向关联:档案属于一个用户
  @BelongsTo(() => User, { foreignKey: 'userId' })
  user?: User;
}

配置参数

target(第一个参数)

  • 类型: () => ClassClass
  • 描述: 目标模型类或返回目标模型类的工厂函数
  • 必需: 是
  • 示例: () => UserProfile

options(第二个参数)

foreignKey

  • 类型: string
  • 描述: 目标表中的外键字段名(数据库列名)
  • 默认值: ${当前表名}_id(自动推断)
  • 示例: 'user_id'

localKey

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

lazy

  • 类型: boolean
  • 描述: 是否延迟加载
  • 默认值: true

查询 Has One 关联

预加载关联数据

ts
import { getORM } from '@ibestservices/ibest-orm';

const orm = getORM();

// 查询用户及其档案信息
const user = orm.query(User)
  .with('profile')
  .where({ id: 1 })
  .first();

console.log('用户信息:', user);
// 输出:
// {
//   id: 1,
//   name: "张三",
//   email: "zhangsan@example.com",
//   profile: {
//     id: 1,
//     userId: 1,
//     avatar: "avatar1.jpg",
//     bio: "热爱技术的程序员"
//   }
// }

查询多个用户的关联数据

ts
// 查询所有用户及其档案
const users = orm.query(User)
  .with('profile')
  .find();

users.forEach(user => {
  console.log(`用户 ${user.name} 的头像: ${user.profile?.avatar}`);
});

完整示例

ts
import {
  Table, Column, PrimaryKey, HasOne, BelongsTo,
  initORMWithMemory, getORM, ColumnType
} from '@ibestservices/ibest-orm';

// 定义模型
@Table()
class Employee {
  @PrimaryKey()
  id?: number;

  @Column()
  name!: string;

  @HasOne(() => EmployeeDetail, { foreignKey: 'employee_id' })
  detail?: EmployeeDetail;
}

@Table({ name: 'employee_details' })
class EmployeeDetail {
  @PrimaryKey()
  id?: number;

  @Column({ name: 'employee_id', type: ColumnType.INTEGER })
  employeeId?: number;

  @Column()
  address?: string;

  @Column()
  phone?: string;

  @BelongsTo(() => Employee, { foreignKey: 'employeeId' })
  employee?: Employee;
}

// 初始化
const orm = initORMWithMemory();
orm.migrate(Employee, EmployeeDetail);

// 创建数据
const emp = new Employee();
emp.name = '张三';
const empId = orm.insert(emp);

const detail = new EmployeeDetail();
detail.employeeId = empId;
detail.address = '北京市朝阳区';
detail.phone = '13800138000';
orm.insert(detail);

// 查询员工及其详情
const employees = orm.query(Employee).with('detail').find();
console.log(employees[0]?.detail?.address); // '北京市朝阳区'

注意事项

提示

  • Has One 关联通过外键建立关系,确保外键字段存在
  • 预加载查询会执行两次 SQL 查询:先查主表,再查关联表
  • 关联数据为 null/undefined 时表示没有对应的关联记录

注意

  • 外键字段应该有适当的索引以提高查询性能
  • 删除主记录时要考虑关联数据的处理
  • 一对一关联中,关联表的外键应该是唯一的