跳转到主要内容

装饰器参考

实体装饰器

@Entity

将您的模型标记为实体。实体是一个被转化为数据库表的类。 您可以在实体中指定表名:

@Entity("users")
export class User {}

这段代码将创建一个名为 "users" 的数据库表。

您还可以指定一些额外的实体选项:

  • name - 表名。如果未指定,则表名从实体类名生成。
  • database - 选定数据库服务器中的数据库名。
  • schema - 模式名。
  • engine - 在创建表时要设置的数据库引擎(仅适用于某些数据库)。
  • synchronize - 值为 false 的实体将被跳过进行模式更新。
  • orderBy - 当使用 find 操作和 QueryBuilder 时,指定实体的默认排序方式。

示例:

@Entity({
name: "users",
engine: "MyISAM",
database: "example_dev",
schema: "schema_with_best_tables",
synchronize: false,
orderBy: {
name: "ASC",
id: "DESC",
},
})
export class User {}

了解更多关于实体的信息。

@ViewEntity

视图实体是映射到数据库视图的类。

@ViewEntity() 接受以下选项:

  • name - 视图名称。如果未指定,则视图名称将根据实体类名生成。
  • database - 选定的数据库服务器中的数据库名称。
  • schema - 模式名称。
  • expression - 视图定义。必需参数

expression 可以是包含正确转义的列和表的字符串,具体取决于所使用的数据库(例如在 Postgres 中):

@ViewEntity({
expression: `
SELECT "post"."id" "id", "post"."name" AS "name", "category"."name" AS "categoryName"
FROM "post" "post"
LEFT JOIN "category" "category" ON "post"."categoryId" = "category"."id"
`,
})
export class PostCategory {}

或者是 QueryBuilder 的实例:

@ViewEntity({
expression: (dataSource: DataSource) =>
dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId"),
})
export class PostCategory {}

注意:由于驱动程序的限制,不支持参数绑定。请改为使用字面量参数。

@ViewEntity({
expression: (dataSource: DataSource) =>
dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId")
.where("category.name = :name", { name: "Cars" }) // <-- 这是错误的
.where("category.name = 'Cars'"), // <-- 这是正确的
})
export class PostCategory {}

了解更多关于视图实体的信息。

Column decorators

@Column

将实体中的属性标记为表列。

示例:

@Entity("users")
export class User {
@Column({ primary: true })
id: number

@Column({ type: "varchar", length: 200, unique: true })
firstName: string

@Column({ nullable: true })
lastName: string

@Column({ default: false })
isActive: boolean
}

@Column 接受多个选项:

  • type: ColumnType - 列类型。支持的列类型之一。
  • name: string - 数据库表中的列名。默认情况下,列名从属性名生成。可以通过指定自己的名称来更改它。
  • length: string|number - 列类型的长度。例如,如果您想创建 varchar(150) 类型,可以指定列类型和长度选项。
  • width: number - 列类型的显示宽度。仅适用于MySQL整数类型
  • onUpdate: string - ON UPDATE 触发器。仅在MySQL中使用。
  • nullable: boolean - 确定列是否可以为 NULL,还是必须始终为 NOT NULL。默认情况下,列为 nullable: false
  • update: boolean - 指示列值是否在 "save" 操作时更新。如果为 false,则只能在首次插入对象时写入该值。默认值为 true
  • insert: boolean - 指示列值是否在首次插入对象时设置。默认值为 true
  • select: boolean - 定义在进行查询时是否默认隐藏此列。当设置为 false 时,标准查询不会显示该列的数据。默认情况下,列为 select: true
  • default: string - 添加列的数据库级 DEFAULT 值。
  • primary: boolean - 将列标记为主键。与使用 @PrimaryColumn 相同。
  • unique: boolean - 将列标记为唯一列(创建唯一约束)。默认值为 false
  • comment: string - 数据库的列注释。不支持所有数据库类型。
  • precision: number - 十进制(精确数值)列的精度(仅适用于十进制列),它是存储值的最大数字位数。用于某些列类型。
  • scale: number - 十进制(精确数值)列的小数位数,表示小数点右侧的位数,不得大于精度。用于某些列类型。
  • zerofill: boolean - 在数字列上添加 ZEROFILL 属性。仅在 MySQL 中使用。如果为 true,MySQL 会自动在此列上添加 UNSIGNED 属性。
  • unsigned: boolean - 在数字列上添加 UNSIGNED 属性。仅在 MySQL 中使用。
  • charset: string - 定义列的字符集。不受所有数据库类型支持。
  • collation: string - 定义列的排序规则。
  • enum: string[]|AnyEnum - 在 enum 列类型中用于指定允许的枚举值列表。您可以指定值数组或指定枚举类。
  • enumName: string - 生成的枚举类型的名称。如果未指定,则 TypeORM 将从实体和列名生成枚举类型 - 因此,如果您打算在不同表中使用相同的枚举类型,这是必需的。
  • primaryKeyConstraintName: string - 主键约束的名称。如果未指定,则约束名称将根据表名和涉及的列的名称生成。
  • asExpression: string - 生成的列表达式。仅在MySQLPostgres(仅限 "STORED") 中使用。
  • generatedType: "VIRTUAL" | "STORED" - 生成的列类型。仅在MySQLPostgres(仅限 "STORED") 中使用。
  • hstoreType: "object" | "string" - 返回 HSTORE 列的值类型。将值返回为字符串或对象。仅在Postgres中使用。
  • array: boolean - 用于可以是数组的 postgres 和 cockroachdb 列类型(例如 int[])。
  • transformer: ValueTransformer|ValueTransformer[] - 指定在读取或写入数据库时用于(反)编组此列的值转换器(或值转换器数组)。对于数组,值转换器将按照从 entityValue 到 databaseValue 的自然顺序应用,以及从 databaseValue 到 entityValue 的反向顺序。
  • spatialFeatureType: string - 用于空间列的可选要素类型(PointPolygonLineStringGeometry)作为约束。如果未指定,它将像提供了 Geometry 一样运行。仅在 PostgreSQL 和 CockroachDB 中使用。
  • srid: number - 用于空间列的可选空间参考 ID作为约束。如果未指定,它将默认为 0。标准地理坐标(WGS84 数据)对应于 EPSG 4326。仅在 PostgreSQL 和 CockroachDB 中使用。

了解更多关于实体列的信息。

@PrimaryColumn

将实体中的属性标记为表的主键列。 与 @Column 装饰器相同,但将其 primary 选项设置为 true

示例:

@Entity()
export class User {
@PrimaryColumn()
id: number;
}

@PrimaryColumn() 支持自定义主键约束名称:

@Entity()
export class User {
@PrimaryColumn({ primaryKeyConstraintName: "pk_user_id" })
id: number;
}

注意:在使用 primaryKeyConstraintName 时,对于多个主键列,约束名称必须相同。

了解更多关于实体列的信息。

@PrimaryGeneratedColumn

将实体中的属性标记为表生成的主键列。 它创建的列是主键列,其值是自动生成的。

示例:

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
}

@PrimaryGeneratedColumn() 支持自定义主键约束名称:

@Entity()
export class User {
@PrimaryGeneratedColumn({ primaryKeyConstraintName: "pk_user_id" })
id: number;
}

有四种生成策略:

  • increment - 使用 AUTO_INCREMENT / SERIAL / SEQUENCE(取决于数据库类型)生成递增的数字。
  • identity - 仅适用于 PostgreSQL 10+。PostgreSQL 10 以上的版本支持符合 SQL 标准的 IDENTITY 列。当将生成策略标记为 identity 时,该列将使用 GENERATED [ALWAYS|BY DEFAULT] AS IDENTITY 生成。
  • uuid - 生成唯一的 uuid 字符串。
  • rowid - 仅适用于 CockroachDB。使用 unique_rowid() 函数自动生成值。这将使用当前时间戳和执行 INSERTUPSERT 操作的节点的 ID 生成一个 64 位整数。

    注意:使用 rowid 生成策略的属性必须是 string 数据类型。

默认的生成策略是 increment,要将其更改为其他策略,只需将其作为装饰器的第一个参数传递:

@Entity()
export class User {
@PrimaryGeneratedColumn("uuid")
id: string;
}

了解更多关于实体列的信息。

@ObjectIdColumn

将实体中的属性标记为 ObjectId。 此装饰器仅在 MongoDB 中使用。 MongoDB 中的每个实体都必须有一个 ObjectId 列。

示例:

@Entity()
export class User {
@ObjectIdColumn()
id: ObjectId;
}

了解更多关于MongoDB的信息。

@CreateDateColumn

特殊列,自动设置为实体的插入时间。 您不需要向此列写入值-它将自动设置。 示例:

@Entity()
export class User {
@CreateDateColumn()
createdDate: Date;
}

@UpdateDateColumn

特殊列,每次从实体管理器或存储库调用 save 时,都会自动设置为实体的更新时间。 您不需要向此列写入值-它将自动设置。

@Entity()
export class User {
@UpdateDateColumn()
updatedDate: Date;
}

@DeleteDateColumn

特殊列,每次从实体管理器或存储库调用软删除时,都会自动设置为实体的删除时间。 您不需要设置此列-它将自动设置。

TypeORM 的软删除功能利用全局范围只从数据库中获取“未删除”的实体。

如果设置了 @DeleteDateColumn,则默认范围将为“未删除”。

@Entity()
export class User {
@DeleteDateColumn()
deletedDate: Date;
}

@VersionColumn

特殊列,每次从实体管理器或存储库调用 save 时,都会自动设置为实体的版本(增量编号)。 您不需要向此列写入值-它将自动设置。

@Entity()
export class User {
@VersionColumn()
version: number;
}

@Generated

将列标记为生成的值。例如:

@Entity()
export class User {
@Column()
@Generated("uuid")
uuid: string;
}

该值仅在将实体插入数据库之前生成一次。

@VirtualColumn

特殊列,永远不会保存到数据库,因此充当只读属性。 每次从实体管理器调用 findfindOne 时,根据提供的 VirtualColumn 装饰器中的查询函数重新计算值。传递给查询的别名参数在幕后引用生成查询的确切实体别名。

@Entity({ name: "companies", alias: "COMP" })
export class Company extends BaseEntity {
@PrimaryColumn("varchar", { length: 50 })
name: string;

@VirtualColumn({ query: (alias) => `SELECT COUNT("name") FROM "employees" WHERE "companyName" = ${alias}.name` })
totalEmployeesCount: number;

@OneToMany((type) => Employee, (employee) => employee.company)
employees: Employee[];
}

@Entity({ name: "employees" })
export class Employee extends BaseEntity {
@PrimaryColumn("varchar", { length: 50 })
name: string;

@ManyToOne((type) => Company, (company) => company.employees)
company: Company;
}

关系装饰器

@OneToOne

一对一关系是 A 包含一个 B 实例,且 B 仅包含一个 A 实例的关系。 举个例子,UserProfile 实体。 一个用户只能有一个个人资料,而一个个人资料只属于一个用户。

示例:

import { Entity, OneToOne, JoinColumn } from "typeorm";
import { Profile } from "./Profile";

@Entity()
export class User {
@OneToOne((type) => Profile, (profile) => profile.user)
@JoinColumn()
profile: Profile;
}

了解更多关于一对一关系

@ManyToOne

多对一/一对多关系是 A 包含多个 B 实例,但 B 仅包含一个 A 实例的关系。 举个例子,UserPhoto 实体。 一个用户可以拥有多张照片,但每张照片只属于一个用户。

示例:

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { User } from "./User";

@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number;

@Column()
url: string;

@ManyToOne((type) => User, (user) => user.photos)
user: User;
}

了解更多关于多对一/一对多关系

@OneToMany

多对一/一对多关系是 A 包含多个 B 实例,但 B 仅包含一个 A 实例的关系。 举个例子,UserPhoto 实体。 一个用户可以拥有多张照片,但每张照片只属于一个用户。

示例:

import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Photo } from "./Photo";

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@OneToMany((type) => Photo, (photo) => photo.user)
photos: Photo[];
}

了解更多关于多对一/一对多关系

@ManyToMany

多对多关系是 A 包含多个 B 实例,且 B 包含多个 A 实例的关系。 举个例子,QuestionCategory 实体。 一个问题可以有多个分类,而每个分类可以包含多个问题。

示例:

import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToMany,
JoinTable,
} from "typeorm";
import { Category } from "./Category";

@Entity()
export class Question {
@PrimaryGeneratedColumn()
id: number;

@Column()
title: string;

@Column()
text: string;

@ManyToMany((type) => Category)
@JoinTable()
categories: Category[];
}

了解更多关于多对多关系

@JoinColumn

定义关系中包含外键的一侧,并允许您自定义连接列名、引用列名和外键名。

示例:

@Entity()
export class Post {
@ManyToOne((type) => Category)
@JoinColumn({
name: "cat_id",
referencedColumnName: "name",
foreignKeyConstraintName: "fk_cat_id"
})
category: Category;
}

@JoinTable

用于多对多关系,描述了“连接”表的连接列。 连接表是由 TypeORM 自动创建的一个特殊的、单独的表,其中的列与相关实体相对应。 您可以通过 joinColumninverseJoinColumn 属性更改生成的“连接”表的名称、连接表中的列名、它们的引用列以及创建的外键名。 您还可以将参数 synchronize 设置为 false 来跳过模式更新(与 @Entity 中的方式相同)。

示例:

@Entity()
export class Post {
@ManyToMany((type) => Category)
@JoinTable({
name: "question_categories",
joinColumn: {
name: "question",
referencedColumnName: "id",
foreignKeyConstraintName: "fk_question_categories_questionId"
},
inverseJoinColumn: {
name: "category",
referencedColumnName: "id",
foreignKeyConstraintName: "fk_question_categories_categoryId"
},
synchronize: false,
})
categories: Category[];
}

如果目标表具有复合主键,则必须将属性数组发送到 @JoinTable 装饰器中。

@RelationId

将特定关联关系的id(或ids)加载到属性中。 例如,如果您的Post实体中有一个多对一的category关系, 您可以通过使用@RelationId标记一个新的属性来获得新的类别id。 示例:

@Entity()
export class Post {
@ManyToOne((type) => Category)
category: Category

@RelationId((post: Post) => post.category) // 需要指定目标关联关系
categoryId: number
}

这个功能适用于所有类型的关联关系,包括多对多关系:

@Entity()
export class Post {
@ManyToMany((type) => Category)
categories: Category[]

@RelationId((post: Post) => post.categories)
categoryIds: number[]
}

关联关系id仅用于表示。 在链接值时,不会添加/删除/更改底层关联关系。

Subscriber和listener装饰器

@AfterLoad

您可以在实体中定义一个任意名称的方法,并用@AfterLoad标记它, TypeORM将在使用QueryBuilder或repository/manager的查找方法加载实体时调用它。 示例:

@Entity()
export class Post {
@AfterLoad()
updateCounters() {
if (this.likesCount === undefined) this.likesCount = 0
}
}

了解更多关于listeners

@BeforeInsert

您可以在实体中定义一个任意名称的方法,并用@BeforeInsert标记它, TypeORM将在使用repository/manager的save方法插入实体之前调用它。 示例:

@Entity()
export class Post {
@BeforeInsert()
updateDates() {
this.createdDate = new Date()
}
}

了解更多关于listeners

@AfterInsert

您可以在实体中定义一个任意名称的方法,并用@AfterInsert标记它, TypeORM将在使用repository/manager的save方法插入实体之后调用它。 示例:

@Entity()
export class Post {
@AfterInsert()
resetCounters() {
this.counters = 0
}
}

了解更多关于listeners

@BeforeUpdate

您可以在实体中定义一个任意名称的方法,并用@BeforeUpdate标记它, TypeORM将在使用repository/manager的save方法更新现有实体之前调用它。 示例:

@Entity()
export class Post {
@BeforeUpdate()
updateDates() {
this.updatedDate = new Date()
}
}

了解更多关于listeners

@AfterUpdate

您可以在实体中定义一个任意名称的方法,并用@AfterUpdate标记它, TypeORM将在使用repository/manager的save方法更新现有实体之后调用它。 示例:

@Entity()
export class Post {
@AfterUpdate()
updateCounters() {
this.counter = 0
}
}

了解更多关于listeners

@BeforeRemove

您可以在实体中定义一个任意名称的方法,并用@BeforeRemove标记它, TypeORM将在使用repository/manager的remove方法移除实体之前调用它。 示例:

@Entity()
export class Post {
@BeforeRemove()
updateStatus() {
this.status = "removed"
}
}

了解更多关于listeners

@AfterRemove

您可以在实体中定义一个任意名称的方法,并用@AfterRemove标记它, TypeORM将在使用repository/manager的remove方法移除实体之后调用它。 示例:

@Entity()
export class Post {
@AfterRemove()
updateStatus() {
this.status = "removed"
}
}

了解更多关于listeners

@BeforeSoftRemove

您可以在实体中定义一个任意名称的方法,并用@BeforeSoftRemove标记它, TypeORM将在使用repository/manager的softRemove方法软删除实体之前调用它。 示例:

@Entity()
export class Post {
@BeforeSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}

了解更多关于listeners

@AfterSoftRemove

您可以在实体中定义一个任意名称的方法,并用@AfterSoftRemove标记它, TypeORM将在使用repository/manager的softRemove方法软删除实体之后调用它。 示例:

@Entity()
export class Post {
@AfterSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}

了解更多关于listeners

@BeforeRecover

您可以在实体中定义一个任意名称的方法,并用@BeforeRecover标记它, TypeORM将在使用repository/manager的recover方法恢复实体之前调用它。 示例:

@Entity()
export class Post {
@BeforeRecover()
updateStatus() {
this.status = "recovered"
}
}

了解更多关于listeners

@AfterRecover

您可以在实体中定义一个任意名称的方法,并用@AfterRecover标记它, TypeORM将在使用repository/manager的recover方法恢复实体之后调用它。 示例:

@Entity()
export class Post {
@AfterRecover()
updateStatus() {
this.status = "recovered"
}
}

了解更多关于listeners

@EventSubscriber

将一个类标记为事件订阅者,可以监听特定实体事件或任何实体的事件。 事件是使用QueryBuilder和repository/manager方法触发的。 示例:

@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface<Post> {
/**
* 表示此订阅者只监听Post事件。
*/
listenTo() {
return Post
}

/**
* 在插入post之前调用。
*/
beforeInsert(event: InsertEvent<Post>) {
console.log(`BEFORE POST INSERTED: `, event.entity)
}
}

您可以实现EntitySubscriberInterface中的任何方法。 要监听任何实体,只需省略listenTo方法并使用any

@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface {
/**
* 在实体插入之前调用。
*/
beforeInsert(event: InsertEvent<any>) {
console.log(`BEFORE ENTITY INSERTED: `, event.entity)
}
}

了解更多关于subscribers

其他装饰器

@Index

这个装饰器允许您为特定的列或多列创建数据库索引。 它还允许您将列标记为唯一的。 这个装饰器可以应用于列或实体本身。 当需要在单个列上创建索引时,在列上使用它, 当需要在多个列上创建单个索引时,在实体上使用它。 示例:

@Entity()
export class User {
@Index()
@Column()
firstName: string

@Index({ unique: true })
@Column()
lastName: string
}
@Entity()
@Index(["firstName", "lastName"])
@Index(["lastName", "middleName"])
@Index(["firstName", "lastName", "middleName"], { unique: true })
export class User {
@Column()
firstName: string

@Column()
lastName: string

@Column()
middleName: string
}

了解更多关于indices

@Unique

这个装饰器允许您为特定的列或多列创建数据库唯一约束。 这个装饰器只能应用于实体本身。 您必须将实体字段名称(而不是数据库列名)作为参数指定。

示例:

@Entity()
@Unique(["firstName"])
@Unique(["lastName", "middleName"])
@Unique("UQ_NAMES", ["firstName", "lastName", "middleName"])
export class User {
@Column({ name: "first_name" })
firstName: string

@Column({ name: "last_name" })
lastName: string

@Column({ name: "middle_name" })
middleName: string
}

注意:MySQL将唯一约束存储为唯一索引。

@Check

这个装饰器允许您为特定的列或多列创建数据库检查约束。 这个装饰器只能应用于实体本身。

示例:

@Entity()
@Check(`"firstName" <> 'John' AND "lastName" <> 'Doe'`)
@Check(`"age" > 18`)
export class User {
@Column()
firstName: string

@Column()
lastName: string

@Column()
age: number
}

注意:MySQL不支持检查约束。

@Exclusion

这个装饰器允许您为特定的列或多列创建数据库排除约束。 这个装饰器只能应用于实体本身。

示例:

@Entity()
@Exclusion(`USING gist ("room" WITH =, tsrange("from", "to") WITH &&)`)
export class RoomBooking {
@Column()
room: string

@Column()
from: Date

@Column()
to: Date
}

注意:只有PostgreSQL支持排除约束。