You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Sequelize+TypeScript中实现类似@Embedded的嵌入类功能?

在Sequelize+TypeScript中实现类似JPA @Embedded的属性封装

Sequelize本身没有提供类似Java JPA @Embedded的直接注解,但可以通过**TypeScript访问器(get/set)**结合普通类/接口来实现非实体类的属性封装,以下是具体实现方案:

步骤1:定义非实体的Hobby类型

将Hobby改为普通TypeScript类或接口,不需要继承Model和添加@Table注解(因为它不是独立的数据库实体):

方式1:使用类(支持构造函数)

// Hobby.ts
export class Hobby {
  hobby: string;
  skillLevel: number;

  constructor(hobby: string, skillLevel: number) {
    this.hobby = hobby;
    this.skillLevel = skillLevel;
  }
}

方式2:使用接口(轻量型)

// Hobby.ts
export interface Hobby {
  hobby: string;
  skillLevel: number;
}

步骤2:修改User类实现封装

在User类中保留对应数据库字段的@Column注解,通过访问器将hobby和skill_level字段封装为Hobby对象:

// User.ts
import { Hobby } from './Hobby';
import { Phone } from './Phone';
import { Column, DataType, HasMany, Model, Table } from 'sequelize-typescript';

@Table({ tableName: 'user_test', timestamps: false })
export class User extends Model<User> {
  @Column({
    primaryKey: true,
    autoIncrement: true,
    field: 'id',
    defaultValue: true,
  })
  id: number;

  @Column({ field: 'name', type: DataType.STRING })
  name: string;

  @Column({ field: 'age', type: DataType.INTEGER })
  age: number;

  // 私有字段对应数据库表的原始字段
  @Column({ field: 'hobby', type: DataType.STRING })
  private _hobby: string;

  @Column({ field: 'skill_level', type: DataType.INTEGER })
  private _skillLevel: number;

  // 封装为Hobby对象的访问器
  get hobby(): Hobby {
    // 如果用类:return new Hobby(this._hobby, this._skillLevel);
    // 如果用接口:
    return {
      hobby: this._hobby,
      skillLevel: this._skillLevel
    };
  }

  set hobby(hobbyObj: Hobby) {
    this._hobby = hobbyObj.hobby;
    this._skillLevel = hobbyObj.skillLevel;
  }

  @HasMany(() => Phone)
  phone: Phone[];
}

使用示例

  • 查询时获取封装对象:

    const user = await User.findByPk(1);
    console.log(user.hobby.hobby); // 直接访问封装后的属性
    console.log(user.hobby.skillLevel);
    
  • 设置时直接赋值Hobby对象:

    const user = new User();
    user.hobby = new Hobby('篮球', 5); // 类方式
    // 或接口方式:user.hobby = { hobby: '足球', skillLevel: 4 };
    await user.save();
    

这种方式既保留了数据库字段的映射关系,又实现了属性的逻辑封装,完全符合需求。

内容的提问来源于stack exchange,提问作者Juan Enrique Riquelme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:05:42