实体
实体要么是一个类,要么是一个对象字面量(interface),并且始终有一个主键。
实体使用来自 @deepkit/type
的类型注解标注所需的全部信息。例如,定义主键、各种字段及其校验约束。这些字段反映数据库结构,通常对应一张表或一个集合。
通过 Mapped<'name'>
之类的特殊类型注解,还可以将字段名映射为数据库中的另一个名称。
类
import { entity, PrimaryKey, AutoIncrement, Unique, MinLength, MaxLength } from '@deepkit/type'; @entity.name('user') class User { id: number & PrimaryKey & AutoIncrement = 0; created: Date = new Date; firstName?: string; lastName?: string; constructor( public username: string & Unique & MinLength<2> & MaxLength<16>, public email: string & Unique, ) {} } const database = new Database(new SQLiteDatabaseAdapter(':memory:'), [User]); await database.migrate(); await database.persist(new User('Peter')); const allUsers = await database.query(User).find(); console.log('all users', allUsers);
接口
import { PrimaryKey, AutoIncrement, Unique, MinLength, MaxLength } from '@deepkit/type'; interface User { id: number & PrimaryKey & AutoIncrement = 0; created: Date = new Date; firstName?: string; lastName?: string; username: string & Unique & MinLength<2> & MaxLength<16>; } const database = new Database(new SQLiteDatabaseAdapter(':memory:')); database.register<User>({name: 'user'}); await database.migrate(); const user: User = {id: 0, created: new Date, username: 'Peter'}; await database.persist(user); const allUsers = await database.query<User>().find(); console.log('all users', allUsers);
原始类型
诸如 String、Number(bigint)和 Boolean 等原始数据类型会映射到常见的数据库类型。仅使用 TypeScript 的类型即可。
interface User { logins: number; username: string; pro: boolean; }
主键
每个实体必须且仅有一个主键。不支持多个主键。
主键的基础类型可以是任意类型。常见的是 number 或 UUID。 对于 MongoDB,常用 MongoId 或 ObjectID。
对于数值类型可以使用 AutoIncrement
。
import { PrimaryKey } from '@deepkit/type'; interface User { id: number & PrimaryKey; }
自增
需要在插入时自动递增的字段使用 AutoIncrement
装饰器标注。所有适配器都支持自增值。MongoDB 适配器会使用一个额外的集合来维护计数器。
自增字段是一个自动计数器,只能用于主键。数据库会自动确保 ID 只被使用一次。
import { PrimaryKey, AutoIncrement } from '@deepkit/type'; interface User { id: number & PrimaryKey & AutoIncrement; }
UUID
需要为 UUID(v4)类型的字段使用 UUID 装饰器标注。其运行时类型为 string
,在数据库中多为二进制存储。使用 uuid()
函数可创建一个新的 UUID v4。
import { uuid, UUID, PrimaryKey } from '@deepkit/type'; class User { id: UUID & PrimaryKey = uuid(); }
MongoDB ObjectID
在 MongoDB 中应为 ObjectID 类型的字段需使用 MongoId
装饰器标注。其运行时类型为 string
,在数据库中为 ObjectId
(二进制)。
MongoID 字段在插入时会自动获得新值。字段名不必是 _id
,可以使用任意名称。
import { PrimaryKey, MongoId } from '@deepkit/type'; class User { id: MongoId & PrimaryKey = ''; }
可选 / 可空
可选字段可通过 TypeScript 的 title?: string
或 title: string | null
来声明。应只使用其中一种,通常使用可选的 ?
语法,其在运行时对应 undefined
。
对于所有 SQL 适配器,这两种写法都会使数据库中的列类型为 NULLABLE
。因此它们唯一的区别在于运行时表示的值不同。
在下面的示例中,modified 字段是可选的,因此在运行时可以是 undefined,尽管在数据库中始终表示为 NULL。
import { PrimaryKey } from '@deepkit/type'; class User { id: number & PrimaryKey = 0; modified?: Date; }
此示例展示了可空类型的用法。无论在数据库还是在 JavaScript 运行时都使用 NULL。相较于 modified?: Date
更为啰嗦,且不常使用。
import { PrimaryKey } from '@deepkit/type'; class User { id: number & PrimaryKey = 0; modified: Date | null = null; }
数据库类型映射
|=== |运行时类型|SQLite|MySQL|Postgres|Mongo
|string|text|longtext|text|string |number|float|double|double precision|int/number |boolean|integer(1)|boolean|boolean|boolean |date|text|datetime|timestamp|datetime |array|text|json|jsonb|array |map|text|json|jsonb|object |map|text|json|jsonb|object |union|text|json|jsonb|T |uuid|blob|binary(16)|uuid|binary |ArrayBuffer/Uint8Array/...|blob|longblob|bytea|binary |===
通过 DatabaseField
可以将字段映射为任意数据库类型。该类型必须是有效的 SQL 片段,并会原样传递给迁移系统。
import { DatabaseField } from '@deepkit/type'; interface User { title: string & DatabaseField<{type: 'VARCHAR(244)'}>; }
若要针对特定数据库映射字段,可使用 SQLite
、MySQL
或 Postgres
。
SQLite
import { SQLite } from '@deepkit/type'; interface User { title: string & SQLite<{type: 'text'}>; }
MySQL
import { MySQL } from '@deepkit/type'; interface User { title: string & MySQL<{type: 'text'}>; }
Postgres
import { Postgres } from '@deepkit/type'; interface User { title: string & Postgres<{type: 'text'}>; }