装饰器参考手册
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
实体装饰器
@Entity
将模型标记为实体。实体是会被转换为数据库表的类。 你可以在实体中指定表名:
@Entity("users")
export class User {}
这段代码将创建名为 "users" 的数据库表。
你还可以指定其他实体选项:
-
name- 表名。如果未指定,则根据实体类名生成。 -
database- 所选 DB 服务器中的数据库名称。 -
schema- 模式名称。 -
comment- 数据库表注释。并非所有数据库类型都支持。目前支持 MySQL、MariaDB、PostgreSQL 和 SAP HANA。 -
engine- 建表时使用的数据库引擎(仅部分数据库支持)。 -
synchronize- 标记为false的实体将跳过模式更新。 -
orderBy- 为find操作和QueryBuilder指定实体默认排序方式。
示例:
@Entity({
name: "users",
engine: "MyISAM",
database: "example_dev",
schema: "schema_with_best_tables",
comment: "This is users table",
synchronize: false,
orderBy: {
name: "ASC",
id: "DESC",
},
})
export class User {}
了解更多关于实体的内容。
@ViewEntity
视图实体是映射到数据库视图的类。
@ViewEntity() 接受以下选项:
-
name- 视图名称。如果未指定,则根据实体类名生成。 -
database- 所选 DB 服务器中的数据库名称。 -
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" }) // <-- this is wrong
.where("category.name = 'Cars'"), // <-- and this is right
})
export class PostCategory {}
了解更多关于视图实体的内容。
列装饰器
@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 整数类型)。新版本 MySQL 已弃用,TypeORM 将在后续版本移除该选项。 -
onUpdate: string-ON UPDATE触发器(仅 MySQL 支持) -
nullable: boolean- 决定列是否允许为NULL(默认nullable: false表示必须为NOT NULL)。 -
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- 十进制(精确数值)列的精度(仅适用于 decimal 列),表示存储数值的最大位数。用于某些列类型。 -
scale: number- 十进制(精确数值)列的小数位数(仅适用于 decimal 列),表示小数点右侧的位数且不得超过精度值。用于某些列类型。 -
zerofill: boolean- 为数值列添加ZEROFILL属性(仅 MySQL 支持)。设为true时 MySQL 会自动添加UNSIGNED属性。新版本 MySQL 已弃用,TypeORM 将在后续版本移除该选项。建议改用字符列和LPAD函数。 -
unsigned: boolean- 为数值列添加UNSIGNED属性(仅 MySQL 支持)。 -
charset: string- 定义列字符集(并非所有数据库类型都支持)。 -
collation: string- 定义列排序规则。 -
enum: string[]|AnyEnum- 用于enum列类型,指定允许的枚举值列表(可传入值数组或枚举类)。 -
enumName: string- 生成的枚举类型名称。未指定时 TypeORM 会根据实体和列名生成,如需跨表复用相同枚举类型则必须指定。 -
primaryKeyConstraintName: string- 主键约束名称。未指定时根据表名和相关列名生成。 -
generatedType: "VIRTUAL"|"STORED"- 生成列类型(仅支持 MySQL 和 Postgres(仅 "STORED"))。 -
hstoreType: "object"|"string"-HSTORE列返回类型(返回字符串或对象,仅 Postgres 支持)。 -
array: boolean- 用于支持数组类型的列(如 int[]),适用于 postgres 和 cockroachdb。 -
transformer: ValueTransformer|ValueTransformer[]- 指定用于读写数据库时对该列进行值(解)编组的转换器(或转换器数组)。对于数组,值转换器将按自然顺序从 entityValue 到 databaseValue 应用,并按相反顺序从 databaseValue 到 entityValue 应用。 -
spatialFeatureType: string- 可选的要素类型(Point、Polygon、LineString、Geometry),用作空间列的约束。如果未指定,其行为将如同提供了Geometry。仅 PostgreSQL 和 CockroachDB 支持。 -
srid: number- 可选的空间参考标识符,用作空间列的约束。如果未指定,则默认为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+。Postgres 10 以上版本支持符合 SQL 标准的 IDENTITY 列。将生成策略标记为identity时,将使用GENERATED [ALWAYS|BY DEFAULT] AS IDENTITY生成列。 -
uuid- 生成唯一的uuid字符串。 -
rowid- 仅适用于 CockroachDB。值通过unique_rowid()函数自动生成。该函数根据当前时间戳和执行INSERT或UPSERT操作的节点 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 方法时,自动更新为实体修改时间。无需手动赋值,系统自动设置。
在由于冲突而发生更新的 upsert 操作期间,该列也会自动更新。
@Entity()
export class User {
@UpdateDateColumn()
updatedDate: Date
}
@DeleteDateColumn
特殊列,通过实体管理器或存储库执行软删除时自动设置为删除时间。无需手动赋值,系统自动设置。
TypeORM 的软删除功能通过全局作用域实现,默认仅从数据库提取"未删除"的实体。
若设置了 @DeleteDateColumn,默认作用域将为"未删除"状态。
@Entity()
export class User {
@DeleteDateColumn()
deletedDate: Date
}
@VersionColumn
特殊列,每次通过实体管理器或存储库调用 save 方法时,该列会自动更新为实体的版本号(递增数值)。您无需手动写入值——系统将自动设置该值。
在由于冲突而发生更新的 upsert 操作期间,该列也会自动更新。
@Entity()
export class User {
@VersionColumn()
version: number
}
@Generated
将列标记为自动生成值。例如:
@Entity()
export class User {
@Column()
@Generated("uuid")
uuid: string
}
该值仅在实体插入数据库前生成一次。
@VirtualColumn
特殊列,其值永不保存至数据库,因此作为只读属性存在。每次通过实体管理器调用 find 或 findOne 方法时,该值会根据 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 的一个实例。以 User 和 Profile 实体为例:用户只能拥有一个个人资料,而每个资料仅属于单一用户。示例:
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 的一个实例。以 User 和 Photo 实体为例:用户可拥有多张照片,但每张照片仅属于单一用户。示例:
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 的一个实例。以 User 和 Photo 实体为例:用户可拥有多张照片,但每张照片仅属于单一用户。示例:
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 的多个实例。以 Question 和 Category 实体为例:问题可属于多个分类,每个分类可包含多个问题。示例:
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
用于 many-to-many 关系,描述"联结表"的连接列。联结表是 TypeORM 自动生成的独立特殊表,其列指向相关实体。您可通过 joinColumn 和 inverseJoinColumn 属性修改联结表名称、联结表内的列名及其引用列,以及创建的外键名称。也可设置参数 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(或多个 ID)加载到属性中。例如,若 Post 实体中存在多对一 category 关系,可通过标记新属性为 @RelationId 来获取新的分类 ID。示例:
@Entity()
export class Post {
@ManyToOne((type) => Category)
category: Category
@RelationId((post: Post) => post.category) // you need to specify target relation
categoryId: number
}
此功能适用于所有类型的关系,包括 many-to-many:
@Entity()
export class Post {
@ManyToMany((type) => Category)
categories: Category[]
@RelationId((post: Post) => post.categories)
categoryIds: number[]
}
关系ID仅用于表示目的。 更改该值并不会实际添加/移除/修改底层关系。
订阅者与监听器装饰器
@AfterLoad
您可以在实体中定义任意名称的方法并用 @AfterLoad 标记,
TypeORM 将在每次通过 QueryBuilder 或仓库/管理器查询方法加载实体时调用它。
示例:
@Entity()
export class Post {
@AfterLoad()
updateCounters() {
if (this.likesCount === undefined) this.likesCount = 0
}
}
了解更多关于监听器的信息。
@BeforeInsert
您可以在实体中定义任意名称的方法并用 @BeforeInsert 标记,
TypeORM 将在通过仓库/管理器 save 方法插入实体前调用它。
示例:
@Entity()
export class Post {
@BeforeInsert()
updateDates() {
this.createdDate = new Date()
}
}
了解更多关于监听器的信息。
@AfterInsert
您可以在实体中定义任意名称的方法并用 @AfterInsert 标记,
TypeORM 将在通过仓库/管理器 save 方法插入实体后调用它。
示例:
@Entity()
export class Post {
@AfterInsert()
resetCounters() {
this.counters = 0
}
}
了解更多关于监听器的信息。
@BeforeUpdate
您可以在实体中定义任意名称的方法并用 @BeforeUpdate 标记,
TypeORM 将在通过仓库/管理器 save 方法更新现有实体前调用它。
示例:
@Entity()
export class Post {
@BeforeUpdate()
updateDates() {
this.updatedDate = new Date()
}
}
了解更多关于监听器的信息。
@AfterUpdate
您可以在实体中定义任意名称的方法并用 @AfterUpdate 标记,
TypeORM 将在通过仓库/管理器 save 方法更新现有实体后调用它。
示例:
@Entity()
export class Post {
@AfterUpdate()
updateCounters() {
this.counter = 0
}
}
了解更多关于监听器的信息。
@BeforeRemove
你可以在实体中定义一个任意名称的方法,并用 @BeforeRemove 标记。TypeORM 会在实体被仓库/管理器的 remove 方法移除之前调用该方法。
示例:
@Entity()
export class Post {
@BeforeRemove()
updateStatus() {
this.status = "removed"
}
}
了解更多关于监听器的信息。
@AfterRemove
您可以在实体中定义任意名称的方法并用 @AfterRemove 标记,
TypeORM 将在通过仓库/管理器 remove 方法移除实体后调用它。
示例:
@Entity()
export class Post {
@AfterRemove()
updateStatus() {
this.status = "removed"
}
}
了解更多关于监听器的信息。
@BeforeSoftRemove
你可以在实体中定义一个任意名称的方法,并用 @BeforeSoftRemove 标记。TypeORM 会在实体被仓库/管理器的 softRemove 方法软删除之前调用该方法。
示例:
@Entity()
export class Post {
@BeforeSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}
了解更多关于监听器的信息。
@AfterSoftRemove
您可以在实体中定义任意名称的方法并用 @AfterSoftRemove 标记,
TypeORM 将在通过仓库/管理器 softRemove 方法软删除实体后调用它。
示例:
@Entity()
export class Post {
@AfterSoftRemove()
updateStatus() {
this.status = "soft-removed"
}
}
了解更多关于监听器的信息。
@BeforeRecover
你可以在实体中定义一个任意名称的方法,并用 @BeforeRecover 标记。TypeORM 会在实体被仓库/管理器的 recover 方法恢复之前调用该方法。
示例:
@Entity()
export class Post {
@BeforeRecover()
updateStatus() {
this.status = "recovered"
}
}
了解更多关于监听器的信息。
@AfterRecover
您可以在实体中定义任意名称的方法,并使用 @AfterRecover 标记,
TypeORM 会在通过 repository/manager 的 recover 方法恢复实体后调用该方法。
示例:
@Entity()
export class Post {
@AfterRecover()
updateStatus() {
this.status = "recovered"
}
}
了解更多关于监听器的信息。
@EventSubscriber
将类标记为事件订阅器,可以监听特定实体事件或任意实体事件。
事件通过 QueryBuilder 和 repository/manager 方法触发。
示例:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface<Post> {
/**
* Indicates that this subscriber only listen to Post events.
*/
listenTo() {
return Post
}
/**
* Called before post insertion.
*/
beforeInsert(event: InsertEvent<Post>) {
console.log(`BEFORE POST INSERTED: `, event.entity)
}
}
您可以实现 EntitySubscriberInterface 中的任何方法。
要监听所有实体事件,只需省略 listenTo 方法并使用 any:
@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface {
/**
* Called before entity insertion.
*/
beforeInsert(event: InsertEvent<any>) {
console.log(`BEFORE ENTITY INSERTED: `, event.entity)
}
}
了解更多关于订阅器的信息。
其他装饰器
@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
}
了解更多关于索引的信息。
@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 支持排他约束
@ForeignKey
此装饰器允许为特定列创建数据库外键, 可应用于单个列或整个实体:
- 单列外键:直接应用于列装饰器
- 多列复合外键:应用于实体类
重要:不要将此装饰器用于关系定义。使用关系装饰器(
@ManyToOne、@OneToOne等)定义关系时, 外键会自动创建。@ForeignKey装饰器仅应在需要创建数据库外键, 但不想定义对应实体关系时使用。
示例:
@Entity("orders")
@ForeignKey(() => City, ["cityId", "countryCode"], ["id", "countryCode"])
export class Order {
@PrimaryColumn()
id: number
@Column("uuid", { name: "user_uuid" })
@ForeignKey<User>("User", "uuid", { name: "FK_user_uuid" })
userUuid: string
@Column({ length: 2 })
@ForeignKey(() => Country, "code")
countryCode: string
@Column()
@ForeignKey("cities")
cityId: number
@Column()
dispatchCountryCode: string
@ManyToOne(() => Country)
dispatchCountry: Country
@Column()
dispatchCityId: number
@ManyToOne(() => City)
dispatchCity: City
}
@Entity("cities")
@Unique(["id", "countryCode"])
export class City {
@PrimaryColumn()
id: number
@Column({ length: 2 })
@ForeignKey("countries", { onDelete: "CASCADE", onUpdate: "CASCADE" })
countryCode: string
@Column()
name: string
}
@Entity("countries")
export class Country {
@PrimaryColumn({ length: 2 })
code: string
@Column()
name: string
}
@Entity("users")
export class User {
@PrimaryColumn({ name: "ref" })
id: number
@Column("uuid", { unique: true })
uuid: string
}