装饰器
实体定义
¥Entity Definition
某些选项会影响 模式生成器 的工作方式,这些选项仅适用于 SQL,这意味着它们仅影响 SQL 驱动程序 - 然而,mongo 没有模式。
¥Some options affect how the Schema Generator works, and those are SQL only, meaning they affect only SQL drivers - whereas, mongo has no schema.
@Entity()
@Entity
装饰器用于将你的模型类标记为实体。不要将其用于抽象基类。
¥@Entity
decorator is used to mark your model classes as entities. Do not use it for abstract base classes.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
tableName | string | yes | 覆盖默认集合/表名。 |
schema | string | yes | 设置模式名称。 |
collection | string | yes | tableName 的别名。 |
comment | string | yes | 为表指定注释。(仅限 SQL) |
repository | () => EntityRepository | yes | 设置 自定义存储库类。 |
discriminatorColumn | string | yes | 对于 单表继承。 |
discriminatorMap | Dictionary<string> | yes | 对于 单表继承。 |
discriminatorValue | number | string | yes | 对于 单表继承。 |
forceConstructor | boolean | yes | 创建托管实体实例时强制使用构造函数 |
abstract | boolean | yes | 将实体标记为抽象,此类实体在发现期间内联。 |
readonly | boolean | yes | 禁用更改跟踪 - 此类实体在刷新期间会被忽略。 |
@Entity({ tableName: 'authors' })
export class Author { ... }
实体属性
¥Entity Properties
@Property()
@Property()
装饰器用于定义常规实体属性。所有以下装饰器都扩展了 @Property()
装饰器,因此你也可以在那里使用它的参数。
¥@Property()
decorator is used to define regular entity property. All following decorators extend the @Property()
decorator, so you can also use its parameters there.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
fieldName | string | yes | 覆盖默认属性名称(参见 命名策略)。 |
type | string | Constructor<Type> | Type | yes | 明确指定属性类型。此值基于当前驱动程序映射(请参阅 元数据提供程序 和 自定义类型)。 |
runtimeType | string | yes | 属性的运行时类型。这是你的属性映射到的 JS 类型,例如 string 或 number ,通常通过 reflect-metadata 自动推断。在某些情况下,推断不起作用,你可能需要明确指定 runtimeType - 最常见的情况是当你使用具有 null 的联合类型(如 foo: number | null )时。 |
returning | boolean | yes | 此属性是否应成为 returning 子句的一部分。仅适用于 PostgreSQL 和 SQLite 驱动程序。 |
onUpdate | () => any | yes | 每次实体更新时自动更新属性值。 |
persist | boolean | yes | 将 false 的列设置为无符号。 |
hydrate | boolean | yes | 设置为 false 以定义 。对持久化 getter 有用。 |
hidden | boolean | yes | 设置为 true 以禁用此属性的水化。 |
groups | string[] | yes | 为 显式序列化 指定序列化组。如果属性未指定任何组,则将包括该属性,否则将仅包括具有匹配组的属性。 |
columnType | string | yes | 为 模式生成器 指定确切的数据库列类型。(仅限 SQL) |
length | number | yes | 数据库列的长度/精度,用于 模式生成器 的 datetime/timestamp/varchar 列类型。(仅限 SQL) |
default | any | yes | 为 模式生成器 指定默认列值。(仅限 SQL) |
unique | boolean | yes | 将 模式生成器 的列设置为可空。(仅限 SQL) |
nullable | boolean | yes | 看到记录器 模式生成器 实体填充了 ,我们需要修复一些问题。(仅限 SQL) |
unsigned | boolean | yes | 将 模式生成器 的列设置为唯一。(仅限 SQL) |
comment | string | yes | 为 模式生成器 指定列的注释。(仅限 SQL) |
version | boolean | yes | 设置为 true 以通过并发字段启用 乐观锁定。(仅限 SQL) |
concurrencyCheck | boolean | yes | 设置为 并发检查 以在 时省略该属性。 |
customOrder | string[] | number[] | boolean[] | yes | 为列指定自定义顺序。(仅限 SQL) |
你可以像往常一样使用属性初始化器。
¥You can use property initializers as usual.
@Property({ length: 50, fieldName: 'first_name' })
name!: string;
@Property({ type: 'date', fieldName: 'born_date' })
born?: string;
@Property({ columnType: 'tinyint' })
age?: number;
@Property({ onUpdate: () => new Date() })
updatedAt = new Date();
@Property()
registered = false;
@PrimaryKey()
@PrimaryKey()
装饰器用于定义实体的唯一主键标识符。
¥@PrimaryKey()
decorator is used to define entity's unique primary key identifier.
@PrimaryKey()
装饰器扩展了@Property()
装饰器,因此你可以使用其所有参数。¥
@PrimaryKey()
decorator extend the@Property()
decorator, so you can use all its parameters.
每个实体都需要至少有一个主键(参见复合主键)。
¥Every entity needs to have at least one primary key (see composite primary keys).
请注意,如果只设置了一个 PrimaryKey,并且它的类型是数字,它将在所有 SQL 驱动程序中自动设置为自动递增。
¥Note that if only one PrimaryKey is set, and it's type is number it will be set to auto incremented automatically in all SQL drivers.
@PrimaryKey()
id!: number; // auto increment PK in SQL drivers
@PrimaryKey({ autoincrement: false })
id!: number; // numeric PK without auto increment
@PrimaryKey()
uuid: string = uuid.v4(); // uuid PK in SQL drivers
@PrimaryKey()
_id!: ObjectId; // ObjectId PK in mongodb driver
@SerializedPrimaryKey()
标有
@SerializedPrimaryKey()
的属性是虚拟的,它不会持久保存到数据库中。¥Property marked with
@SerializedPrimaryKey()
is virtual, it will not be persisted into the database.
对于 MongoDB,你可以定义序列化主键,然后通过 JSON.stringify()
(通过方法 entity.toJSON()
)用于实体序列化。你将能够使用它来操作主键作为字符串。
¥For MongoDB, you can define serialized primary key, which will be then used in entity serialization via JSON.stringify()
(through method entity.toJSON()
). You will be able to use it to manipulate with the primary key as string.
参见 与 MongoDB 一起使用 和 序列化。
¥See Usage with MongoDB and Serializing.
@PrimaryKey()
_id: ObjectId;
@SerializedPrimaryKey()
id!: string;
@Enum()
@Enum()
装饰器扩展了@Property()
装饰器,因此你可以使用其所有参数。¥
@Enum()
decorator extend the@Property()
decorator, so you can use all its parameters.
@Enum()
装饰器可用于数字和字符串枚举。默认情况下,枚举被视为数字,并将在数据库模式中表示为 tinyint/smallint
。对于字符串枚举,如果你在同一文件中定义枚举,则其值将被自动嗅探。
¥@Enum()
decorator can be used for both numeric and string enums. By default, enums are considered numeric, and will be represented in the database schema as tinyint/smallint
. For string enums, if you define the enum in same file, its values will be automatically sniffed.
参见 定义实体。
¥See Defining Entities.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
items | number[] | string[] | () => Dictionary | yes | 明确指定枚举项。 |
@Enum() // with ts-morph metadata provider we do not need to specify anything
enum0 = MyEnum1.VALUE_1;
@Enum(() => MyEnum1) // or @Enum({ items: () => MyEnum1 })
enum1 = MyEnum1.VALUE_1;
@Enum({ type: 'MyEnum2', nullable: true })
enum2?: MyEnum2; // MyEnum2 needs to be defined in current file (can be re-exported)
@Enum({ items: [1, 2, 3] })
enum3 = 3;
@Enum({ items: ['a', 'b', 'c'] })
enum4 = 'a';
@Formula()
@Formula()
装饰器可用于将一些 SQL 代码片段映射到你的实体。SQL 片段可以尽可能复杂,甚至包括子选择。
¥@Formula()
decorator can be used to map some SQL snippet to your entity. The SQL fragment can be as complex as you want and even include subselects.
参见 定义实体。
¥See Defining Entities.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
formula | string | () => string | no | 将成为 select 子句一部分的 SQL 片段。 |
@Formula('obj_length * obj_height * obj_width')
objectVolume?: number;
@Index() and @Unique()
使用 @Index()
创建索引,或使用 @Unique()
创建唯一约束。你可以在实体级别和属性级别使用这些装饰器。要创建复合索引,请在实体级别使用装饰器并通过 properties
选项提供属性名称列表。
¥Use @Index()
to create an index, or @Unique()
to create unique constraint. You can use those decorators both on the entity level and on property level. To create compound index, use the decorator on the entity level and provide list of property names via the properties
option.
参见 定义实体。
¥See Defining Entities.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
name | string | yes | 索引名称 |
properties | string | string[] | yes | 在实体级别使用时必需的属性列表 |
type | string | yes | 索引类型,不适用于 @Unique() 。使用 fulltext 启用对 $fulltext 运算符的支持 |
deferMode | immediate | deferred | yes | 仅适用于 postgres 唯一约束 |
@Entity()
@Index({ properties: ['name', 'age'] }) // compound index, with generated name
@Index({ name: 'custom_idx_name', properties: ['name'] }) // simple index, with custom name
@Unique({ properties: ['name', 'email'] })
export class Author {
@Property()
@Unique()
email!: string;
@Index() // generated name
@Property()
age?: number;
@Index({ name: 'born_index' })
@Property()
born?: string;
}
@Check()
我们可以通过 @Check()
装饰器定义检查约束。我们可以在实体类或实体属性上使用它。它有一个必需的 expression
属性,可以是字符串或回调,用于接收属性名称到列名称的映射。请注意,如果我们想要 TypeScript 建议属性名称,我们需要使用泛型类型参数。
¥We can define check constraints via @Check()
decorator. We can use it either on entity class, or on entity property. It has a required expression
property, that can be either a string or a callback, that receives map of property names to column names. Note that we need to use the generic type argument if we want TypeScript suggestions for the property names.
PostgreSQL、MySQL 8 和 MariaDB 驱动程序目前支持检查约束。SQLite 还支持创建检查约束,但目前尚未实现架构推断。另请注意,SQLite 不支持向现有表添加检查约束。
¥Check constraints are currently supported in PostgreSQL, MySQL 8 and MariaDB drivers. SQLite also supports creating check constraints, but schema inference is currently not implemented. Also note that SQLite does not support adding check constraints to existing tables.
参见 定义实体。
¥See Defining Entities.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
name | string | yes | 约束名称 |
property | string | yes | 属性名称,仅在生成约束名称时使用 |
expression | string | CheckCallback | no | 约束定义,可以是获取属性到列名映射的回调 |
@Entity()
// with generated name based on the table name
@Check({ expression: 'price1 >= 0' })
// with explicit name
@Check({ name: 'foo', expression: columns => `${columns.price1} >= 0` })
// with explicit type argument we get autocomplete on `columns`
@Check<FooEntity>({ expression: columns => `${columns.price1} >= 0` })
export class Book {
@PrimaryKey()
id!: number;
@Property()
price1!: number;
@Property()
@Check({ expression: 'price2 >= 0' })
price2!: number;
@Property({ check: columns => `${columns.price3} >= 0` })
price3!: number;
}
实体关系
¥Entity Relationships
所有关系装饰器都有 entity
、cascade
和 eager
可选参数。如果你使用默认的 ReflectMetadataProvider
,则可能需要 entity
参数。如果你使用 ReflectMetadataProvider
,你将在发现过程中收到有关未定义该参数的警告。
¥All relationship decorators have entity
, cascade
and eager
optional parameters. If you use the default ReflectMetadataProvider
, then entity
parameter might be required You will be warned about it being not defined while required during discovery process if you use ReflectMetadataProvider
.
你也可以使用 type
参数代替它 - 不同之处在于 type
参数需要是字符串,而在 entity
参数中,你可以提供对实体的引用(封装在回调中以克服循环依赖问题),这与 WebStorm 等 IDE 中的重构功能配合得很好。
¥You can also use type
parameter instead of it - the difference being that type
parameter needs to be string, while in entity
parameter you can provide a reference (wrapped in a callback to overcome issues with circular dependencies) to the entity, which plays nice with refactoring features in IDEs like WebStorm.
如果你明确提供
entity
作为引用,它将启用其他引用参数(如inversedBy
或mappedBy
)的类型检查。¥If you explicitly provide
entity
as a reference, it will enable type checks for other reference parameters likeinversedBy
ormappedBy
.
@ManyToOne()
@ManyToOne()
装饰器扩展了@Property()
装饰器,因此你可以使用其所有参数。¥
@ManyToOne()
decorator extend the@Property()
decorator, so you can use all its parameters.
当前实体的许多实例引用被引用实体的一个实例。
¥Many instances of the current Entity refer to One instance of the referred Entity.
有关更多示例,请参阅 定义实体。
¥See Defining Entities for more examples.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
entity | string | () => EntityName | yes | 设置目标实体类型。 |
cascade | Cascade[] | yes | 设置为 true 以通过版本字段启用 。默认为 [Cascade.PERSIST, Cascade.MERGE] (参见 级联)。 |
eager | boolean | yes | 始终加载关系。(不建议用于多对多关系。) |
inversedBy | (string & keyof T) | (e: T) => any | yes | 指向反向属性名称。 |
ref | boolean | yes | 将实体封装在 Reference 封装器 中。 |
primary | boolean | yes | 使用此关系作为主键。 |
deleteRule | string | yes | 参照完整性。 |
updateRule | string | yes | 参照完整性。 |
deferMode | immediate | deferred | yes | 仅适用于 postgres 唯一约束 |
@ManyToOne()
author1?: Author; // type taken via reflection (TsMorphMetadataProvider)
@ManyToOne(() => Author) // explicit type
author2?: Author;
@ManyToOne({ entity: () => Author, cascade: [Cascade.ALL] }) // options object
author3?: Author;
@OneToOne()
@OneToOne()
装饰器扩展了@Property()
装饰器,因此你可以使用其所有参数。¥
@OneToOne()
decorator extend the@Property()
decorator, so you can use all its parameters.
当前实体的一个实例引用所引用实体的一个实例。
¥One instance of the current Entity refers to One instance of the referred Entity.
有关更多示例,请参阅 定义实体,包括双向 1:1。
¥See Defining Entities for more examples, including bidirectional 1:1.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
entity | string | () => EntityName | yes | 设置目标实体类型。 |
cascade | Cascade[] | yes | 设置为 true 以通过版本字段启用 。默认为 [Cascade.PERSIST, Cascade.MERGE] (参见 级联)。 |
eager | boolean | yes | 始终加载关系。(不建议用于多对多关系。) |
owner | boolean | yes | 明确设置为拥有方(与提供 inversedBy 相同)。 |
inversedBy | (string & keyof T) | (e: T) => any | yes | 指向反向属性名称。 |
mappedBy | (string & keyof T) | (e: T) => any | yes | 指向拥有方属性名称。 |
ref | boolean | yes | 将实体封装在 Reference 封装器 中。 |
orphanRemoval | boolean | yes | 当实体与关系断开时删除它(参见 级联)。 |
joinColumn | string | yes | 在拥有侧覆盖默认数据库列名(参见 命名策略)。 |
primary | boolean | yes | 使用此关系作为主键。 |
deleteRule | string | yes | 参照完整性。 |
updateRule | string | yes | 参照完整性。 |
deferMode | immediate | deferred | yes | 仅适用于 postgres 唯一约束 |
// when none of `owner/inverseBy/mappedBy` is provided, it will be considered owning side
@OneToOne()
bestFriend1!: User;
// side with `inversedBy` is the owning one, to define inverse side use `mappedBy`
@OneToOne({ inversedBy: 'bestFriend1', orphanRemoval: true })
bestFriend2!: User;
// when defining it like this, you need to specifically mark the owning side with `owner: true`
@OneToOne(() => User, user => user.bestFriend2, { owner: true, orphanRemoval: true })
bestFriend3!: User;
@OneToMany()
@OneToMany()
装饰器扩展了@Property()
装饰器,因此你可以使用其所有参数。¥
@OneToMany()
decorator extend the@Property()
decorator, so you can use all its parameters.
当前实体的一个实例对所引用的实体有许多实例(引用)。
¥One instance of the current Entity has Many instances (references) to the referred Entity.
有关更多示例,请参阅 定义实体,包括双向 1:m。
¥See Defining Entities for more examples, including bidirectional 1:m.
你需要使用
Collection<T>
实例初始化值。¥You need to initialize the value with
Collection<T>
instance.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
mappedBy | (string & keyof T) | (e: T) => any | no | 指向拥有方属性名称。 |
entity | string | () => EntityName | yes | 设置目标实体类型。 |
cascade | Cascade[] | yes | 设置为 true 以通过版本字段启用 。默认为 [Cascade.PERSIST, Cascade.MERGE] (参见 级联)。 |
eager | boolean | yes | 始终加载关系。(不建议用于多对多关系。) |
orphanRemoval | boolean | yes | 当实体与连接断开时删除它(参见 级联)。 |
orderBy | { [field: string]: QueryOrder } | yes | 设置默认排序条件。 |
joinColumn | string | yes | 在拥有侧覆盖默认数据库列名(参见 命名策略)。 |
inverseJoinColumn | string | yes | 在反向侧覆盖默认数据库列名(参见 命名策略)。 |
@OneToMany(() => Book, book => book.author)
books1 = new Collection<Book>(this);
@OneToMany({ mappedBy: 'author', cascade: [Cascade.ALL] })
books2 = new Collection<Book>(this); // target entity type can be read via `TsMorphMetadataProvider` too
@ManyToMany()
@ManyToMany()
装饰器扩展了@Property()
装饰器,因此你可以使用其所有参数。¥
@ManyToMany()
decorator extend the@Property()
decorator, so you can use all its parameters.
当前实体的许多实例引用被引用实体的许多实例。
¥Many instances of the current Entity refers to Many instances of the referred Entity.
有关更多示例,请参阅 定义实体,包括双向 m:n。
¥See Defining Entities for more examples, including bidirectional m:n.
你需要使用
Collection<T>
实例初始化值。¥You need to initialize the value with
Collection<T>
instance.
参数 | 类型 | 可选 | 描述 |
---|---|---|---|
entity | string | () => EntityName | yes | 设置目标实体类型。 |
cascade | Cascade[] | yes | 设置为 true 以通过版本字段启用 。默认为 [Cascade.PERSIST, Cascade.MERGE] (参见 级联)。 |
eager | boolean | yes | 始终加载关系。(不建议用于多对多关系。) |
owner | boolean | yes | 明确设置为拥有方(与提供 inversedBy 相同)。 |
inversedBy | (string & keyof T) | (e: T) => any | yes | 指向反向属性名称。 |
mappedBy | (string & keyof T) | (e: T) => any | yes | 指向拥有方属性名称。 |
orderBy | { [field: string]: QueryOrder } | yes | 设置默认排序条件。 |
fixedOrder | boolean | yes | 强制集合中项目的稳定插入顺序(参见 集合)。 |
fixedOrderColumn | string | yes | 覆盖默认顺序列名(id )。 |
pivotTable | string | yes | 覆盖数据透视表的默认名称(参见 命名策略)。 |
joinColumn | string | yes | 在拥有侧覆盖默认数据库列名(参见 命名策略)。 |
inverseJoinColumn | string | yes | 在反向侧覆盖默认数据库列名(参见 命名策略)。 |
@ManyToMany({ entity: () => BookTag, cascade: [], fixedOrderColumn: 'order' })
tags = new Collection<BookTag>(this); // m:n with autoincrement PK
@ManyToMany(() => BookTag, undefined, { pivotTable: 'book_to_tag_unordered', orderBy: { name: QueryOrder.ASC } })
tagsUnordered = new Collection<BookTag>(this); // m:n with composite PK
生命周期钩子
¥Lifecycle Hooks
当实体持久化时,你可以使用生命周期钩子来运行一些代码。你可以使用它们标记任何实体方法,也可以使用相同的钩子标记多个方法。
¥You can use lifecycle hooks to run some code when entity gets persisted. You can mark any of entity methods with them, you can also mark multiple methods with same hook.
所有钩子都支持异步方法,但有一个异常 -
@OnInit
。¥All hooks support async methods with one exception -
@OnInit
.
@OnInit()
在创建实体的新实例时触发,手动 em.create()
,或从数据库加载新实体时自动创建
¥Fired when new instance of entity is created, either manually em.create()
, or automatically when new entities are loaded from database
当你通过其构造函数(
new MyEntity()
)手动创建实体时,不会触发@OnInit
¥
@OnInit
is not fired when you create the entity manually via its constructor (new MyEntity()
)
@OnInit()
doStuffOnInit(args: EventArgs<this>) {
this.fullName = `${this.firstName} - ${this.lastName}`; // initialize shadow property
}
@OnLoad()
从数据库加载新实体时触发。与 @InInit()
不同,这将仅针对完全加载的实体(而不是引用)触发。方法可以是 async
。
¥Fired when new entities are loaded from database. Unlike @InInit()
, this will be fired only for fully loaded entities (not references). The method can be async
.
@OnLoad()
async doStuffOnLoad(args: EventArgs<this>) {
// ...
}
@BeforeCreate()
在将新实体持久化到数据库中之前立即触发。
¥Fired right before we persist the new entity into the database.
@BeforeCreate()
async doStuffBeforeCreate(args: EventArgs<this>) {
// ...
}
@AfterCreate()
在数据库中创建新实体并合并到身份映射后立即触发。由于 MikroORM 将每个单个实体关系封装在 EntityManager
或 wrap(entity).init()
实例中(出于类型安全),这将使内置的 对任何封装的关系视而不见。
¥Fired right after the new entity is created in the database and merged to identity map. Since this event entity will have reference to EntityManager
and will be enabled to call wrap(entity).init()
method (including all entity references and collections).
@AfterCreate()
async doStuffAfterCreate(args: EventArgs<this>) {
// ...
}
@BeforeUpdate()
在更新数据库中的实体之前立即触发。
¥Fired right before we update the entity in the database.
@BeforeUpdate()
async doStuffBeforeUpdate(args: EventArgs<this>) {
// ...
}
@AfterUpdate()
在数据库中更新实体后立即触发。
¥Fired right after the entity is updated in the database.
@AfterUpdate()
async doStuffAfterUpdate(args: EventArgs<this>) {
// ...
}
@BeforeDelete()
在从数据库中删除记录之前立即触发。它仅在删除实体或实体引用时触发,而不是在通过查询删除记录时触发。
¥Fired right before we delete the record from database. It is fired only when removing entity or entity reference, not when deleting records by query.
@BeforeDelete()
async doStuffBeforeDelete(args: EventArgs<this>) {
// ...
}
@AfterDelete()
记录从数据库中删除后立即触发,并从身份映射中取消设置。
¥Fired right after the record gets deleted from database, and it is unset from the identity map.
@AfterDelete()
async doStuffAfterDelete(args: EventArgs<this>) {
// ...
}