声明模型
IBest-ORM 通过装饰器将 Class 实体类映射到数据库表,简化数据库交互。了解如何定义模型,是充分利用 IBest-ORM 全部功能的基础。
模型定义
模型是使用 @Table 装饰器定义的类。这些类可以包含具有基本类型的属性,通过 @Column、@PrimaryKey 等装饰器映射到数据库字段。
基础示例
ts
import { Table, Column, PrimaryKey, ColumnType } from '@ibestservices/ibest-orm';
@Table() // 自动推断表名为 'user'
export class User {
@PrimaryKey() // 主键,默认自增
id?: number;
@Column() // 自动推断为 TEXT
name?: string;
@Column({ type: ColumnType.INTEGER })
age?: number;
}自定义表名
ts
@Table({ name: 'users' }) // 指定表名为 'users'
export class User {
// ...
}装饰器详解
@Table
标记类为数据表实体。
ts
@Table() // 自动推断表名(类名转蛇形)
@Table({ name: 'custom_table' }) // 自定义表名@PrimaryKey
定义主键字段。
ts
@PrimaryKey() // 默认自增
id?: number;
@PrimaryKey({ autoIncrement: false }) // 非自增主键
id?: number;@Column
定义普通列。
ts
// 自动推断类型
@Column()
name?: string;
// 显式指定类型
@Column({ type: ColumnType.INTEGER })
age?: number;
// 自定义列名
@Column({ name: 'user_name' })
name?: string;
// 非空约束
@Column({ notNull: true })
email?: string;
// 默认值
@Column({ defaultValue: 0 })
status?: number;@NotNull
标记字段为非空(可与 @Column 配合使用)。
ts
@NotNull()
@Column()
name?: string;@CreatedAt
自动记录创建时间。
ts
@CreatedAt() // 默认列名 'created_at'
createdAt?: string;
@CreatedAt({ name: 'create_time' }) // 自定义列名
createTime?: string;@UpdatedAt
自动记录更新时间。
ts
@UpdatedAt() // 默认列名 'updated_at'
updatedAt?: string;@SoftDelete
标记软删除字段。
ts
@SoftDelete() // 默认列名 'deleted_at'
deletedAt?: string;
@SoftDelete({ name: 'delete_time' }) // 自定义列名
deleteTime?: string;字段类型
IBest-ORM 支持以下字段类型:
| ColumnType | SQLite 类型 | TypeScript 类型 |
|---|---|---|
INTEGER | INTEGER | number |
REAL | REAL | number |
TEXT | TEXT | string |
BLOB | BLOB | Uint8Array |
类型自动推断
IBest-ORM 会根据属性名自动推断类型:
ts
// 自动推断为 INTEGER
id?: number; // 包含 'id'
userId?: number; // 以 'id' 结尾
count?: number; // 以 'count' 结尾
age?: number; // 常见整数字段
status?: number;
// 自动推断为 REAL
price?: number; // 包含 'price'
amount?: number; // 包含 'amount'
rate?: number; // 包含 'rate'
score?: number; // 包含 'score'
// 默认推断为 TEXT
name?: string;
description?: string;复合主键
IBest-ORM 支持复合主键:
ts
@Table()
export class OrderItem {
@PrimaryKey({ autoIncrement: false })
orderId?: number;
@PrimaryKey({ autoIncrement: false })
productId?: number;
@Column()
quantity?: number;
}生成的 SQL:
sql
CREATE TABLE order_item (
order_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER,
PRIMARY KEY (order_id, product_id)
);完整示例
ts
import {
Table, Column, PrimaryKey, NotNull,
CreatedAt, UpdatedAt, SoftDelete, ColumnType
} from '@ibestservices/ibest-orm';
@Table({ name: 'articles' })
export class Article {
@PrimaryKey()
id?: number;
@NotNull()
@Column()
title?: string;
@Column({ type: ColumnType.TEXT })
content?: string;
@Column({ type: ColumnType.INTEGER, defaultValue: 0 })
viewCount?: number;
@Column({ name: 'author_id', type: ColumnType.INTEGER })
authorId?: number;
@CreatedAt()
createdAt?: string;
@UpdatedAt()
updatedAt?: string;
@SoftDelete()
deletedAt?: string;
}约定
IBest-ORM 遵循以下约定:
- 表名:类名自动转换为蛇形命名(如
UserProfile→user_profile) - 列名:属性名自动转换为蛇形命名(如
createdAt→created_at) - 主键:名为
id的字段自动识别为主键 - 时间戳:
@CreatedAt和@UpdatedAt装饰的字段自动管理
遵循这些约定可以大大减少配置代码量。
与 HarmonyOS 状态管理装饰器混用
IBest-ORM 支持与 HarmonyOS 状态管理 V2 装饰器(@ObservedV2、@Trace)混合使用,方便在 UI 中实现数据响应式更新。
支持的装饰器
| 装饰器 | 支持状态 | 说明 |
|---|---|---|
@ObservedV2 + @Trace | ✅ 支持 | 状态管理 V2,推荐使用 |
@Observed | ❌ 不支持 | 状态管理 V1,会导致类名丢失 |
使用示例
ts
import { Table, Column, PrimaryKey, ColumnType } from '@ibestservices/ibest-orm';
@Table()
@ObservedV2
export class Product {
@PrimaryKey()
id?: number;
@Column()
@Trace name: string = '';
@Column({ type: ColumnType.REAL })
@Trace price: number = 0;
}注意
不支持 V1 的 @Observed 装饰器
HarmonyOS 状态管理 V1 的 @Observed 装饰器会将类的 name 属性设置为空字符串,导致 IBest-ORM 无法正确识别模型类名,从而引发元数据查找失败。
如果您需要在 UI 中使用响应式数据,请使用状态管理 V2 的 @ObservedV2 + @Trace 组合。
装饰器顺序
当混合使用多个装饰器时,建议按以下顺序排列:
ts
@Table() // ORM 装饰器在最外层
@ObservedV2 // 状态管理装饰器在内层
export class Product {
@PrimaryKey() // ORM 字段装饰器
id?: number;
@Column() // ORM 字段装饰器在前
@Trace // 状态管理装饰器在后
name: string = '';
}关联关系
IBest-ORM 支持定义实体间的关联关系:
ts
import { HasMany, BelongsTo, HasOne, ManyToMany } from '@ibestservices/ibest-orm';
@Table()
export class User {
@PrimaryKey()
id?: number;
@Column()
name?: string;
@HasMany(() => Post, 'authorId')
posts?: Post[];
@HasOne(() => Profile, 'userId')
profile?: Profile;
}
@Table()
export class Post {
@PrimaryKey()
id?: number;
@Column()
title?: string;
@Column()
authorId?: number;
@BelongsTo(() => User, 'authorId')
author?: User;
}详细的关联关系用法请参考 关联查询 章节。