跳至主内容区

实体

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

什么是实体?

实体是一个映射到数据库表(使用 MongoDB 时为集合)的类。 您可以通过定义新类并使用 @Entity() 标记来创建实体:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"

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

@Column()
firstName: string

@Column()
lastName: string

@Column()
isActive: boolean
}

这将创建以下数据库表:

+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| firstName | varchar(255) | |
| lastName | varchar(255) | |
| isActive | boolean | |
+-------------+--------------+----------------------------+

基础实体由列(columns)和关系(relations)组成。 每个实体必须包含一个主列(使用 MongoDB 时为 ObjectId 列)。

每个实体都必须在数据源配置中注册:

import { DataSource } from "typeorm"
import { User } from "./entities/User"

const myDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [User],
})

或者您可以指定包含所有实体的整个目录——它们都会被自动加载:

import { DataSource } from "typeorm"

const dataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [__dirname + "/entities/**/*{.js,.ts}"],
})

若想为 User 实体指定替代表名,可在 @Entity 中设置:@Entity("my_users")。 要为应用中所有数据库表设置基础前缀,可在数据源配置中指定 entityPrefix

使用实体构造函数时,其参数必须为可选参数。因为 ORM 从数据库加载数据时会创建实体类的实例,此时无法感知您的构造函数参数。

更多 @Entity 参数请参阅装饰器参考

实体列

数据库表由列组成,因此实体也必须包含列。 用 @Column 标记的实体类属性将映射为数据库表的列。

主列

每个实体必须至少有一个主列。 主列有几种类型:

  • @PrimaryColumn() 创建一个主列,可接受任意类型的值。您可指定列类型,若未指定则根据属性类型推断。下例将创建 int 类型的 id,保存前需手动赋值。
import { Entity, PrimaryColumn } from "typeorm"

@Entity()
export class User {
@PrimaryColumn()
id: number
}
  • @PrimaryGeneratedColumn() 创建自增值主列。根据数据库及配置自动生成 auto-increment/serial/sequence/identityint 列。保存前无需手动赋值。
import { Entity, PrimaryGeneratedColumn } from "typeorm"

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
}
  • @PrimaryGeneratedColumn("uuid") 创建自动生成 uuid 的主列。Uuid 是唯一字符串 ID。保存前无需手动赋值。
import { Entity, PrimaryGeneratedColumn } from "typeorm"

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

您也可以创建复合主列:

import { Entity, PrimaryColumn } from "typeorm"

@Entity()
export class User {
@PrimaryColumn()
firstName: string

@PrimaryColumn()
lastName: string
}

使用 save 保存实体时,总会尝试根据实体 id(或多个 id)查找数据库中是否存在该实体。 若找到对应 id,则更新该数据库行。 若不存在对应 id 的行,则插入新行。

通过 id 查找实体可使用 manager.findOneByrepository.findOneBy。例如:

// find one by id with single primary key
const person = await dataSource.manager.findOneBy(Person, { id: 1 })
const person = await dataSource.getRepository(Person).findOneBy({ id: 1 })

// find one by id with composite primary keys
const user = await dataSource.manager.findOneBy(User, {
firstName: "Timber",
lastName: "Saw",
})
const user = await dataSource.getRepository(User).findOneBy({
firstName: "Timber",
lastName: "Saw",
})

特殊列

以下是几种具有附加功能的特殊列类型:

  • @CreateDateColumn 是特殊列,自动设置为实体插入时间。无需手动设置。

  • @UpdateDateColumn 是特殊列,每次调用 save 方法或 upsert 更新操作时自动设置为实体更新时间。无需手动设置。

  • @DeleteDateColumn 是特殊列,每次调用软删除方法时自动设置为实体删除时间。无需手动设置。设置此列后,默认查询范围将排除已删除数据。

  • @VersionColumn 是特殊列,每次调用 save 方法或 upsert 更新操作时自动设置为实体版本号(递增数字)。无需手动设置。

列类型

TypeORM 支持所有最常用的数据库列类型。 列类型是数据库特定的 - 这为您的数据库模式设计提供了更大的灵活性。

您可以在 @Column 的第一个参数中指定列类型, 或在 @Column 的列选项中指定,例如:

@Column("int")

@Column({ type: "int" })

如果你想指定额外的类型参数,可以通过列选项来实现。 例如:

@Column("varchar", { length: 200 })

关于 bigint 类型的注意事项:在 SQL 数据库中使用的 bigint 列类型无法映射到常规的 number 类型,而是将属性映射为 string

enum 列类型

enum 列类型被 postgresmysql 支持。有几种可能的列定义方式:

使用 TypeScript 枚举:

export enum UserRole {
ADMIN = "admin",
EDITOR = "editor",
GHOST = "ghost",
}

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

@Column({
type: "enum",
enum: UserRole,
default: UserRole.GHOST,
})
role: UserRole
}

注意:支持字符串、数字和异构枚举类型。

使用包含枚举值的数组:

export type UserRoleType = "admin" | "editor" | "ghost",

@Entity()
export class User {

@PrimaryGeneratedColumn()
id: number;

@Column({
type: "enum",
enum: ["admin", "editor", "ghost"],
default: "ghost"
})
role: UserRoleType
}

simple-array 列类型

有一种特殊的列类型叫做 simple-array,它可以将原始数组值存储在单个字符串列中。 所有值用逗号分隔。例如:

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

@Column("simple-array")
names: string[]
}
const user = new User()
user.names = ["Alexander", "Alex", "Sasha", "Shurik"]

将会在数据库列中存储为 Alexander,Alex,Sasha,Shurik。 当从数据库加载数据时,这些名称将作为字符串数组返回, 就像您存储时一样。

请注意:存储的值中绝对不允许包含逗号。

simple-json 列类型

有一种特殊的列类型叫做 simple-json,它可以存储任何可以通过 JSON.stringify 序列化后存入数据库的值。当您的数据库不支持原生 JSON 类型时非常有用, 可以轻松存储和加载对象。例如:

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

@Column("simple-json")
profile: { name: string; nickname: string }
}
const user = new User()
user.profile = { name: "John", nickname: "Malkovich" }

将会在数据库列中存储为 {"name":"John","nickname":"Malkovich"} 值。 当从数据库加载数据时,将通过 JSON.parse 还原为原始对象/数组/基本类型

带生成值的列

您可以使用 @Generated 装饰器创建带生成值的列。例如:

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

@Column()
@Generated("uuid")
uuid: string
}

uuid 值将自动生成并存入数据库。

除了 "uuid" 外,还有 "increment"、"identity"(仅限 Postgres 10+)和 "rowid"(仅限 CockroachDB)等生成类型。 但请注意,在某些数据库平台上此类生成类型存在限制(例如某些数据库只允许一个自增列, 或要求自增列必须是主键)。

向量列

向量列(Vector columns)在 MariaDB/MySQL、Microsoft SQL Server、PostgreSQL(通过 pgvector 扩展)和 SAP HANA Cloud 中受到支持,可用于存储和查询向量嵌入(vector embeddings),适用于相似性搜索和机器学习应用场景。

TypeORM 在数据库中支持 vectorhalfvec 两种列类型:

  • vector - 以 4 字节浮点数(单精度)存储向量:

    • MariaDB/MySQL:原生 vector 类型
    • Microsoft SQL Server:原生 vector 类型
    • PostgreSQL:通过 pgvector 扩展提供的 vector 类型
    • SAP HANA Cloud:real_vector 类型的别名
  • halfvec - 以 2 字节浮点数(半精度)存储向量以节省内存:

    • PostgreSQL:通过 pgvector 扩展提供的 halfvec 类型
    • SAP HANA Cloud:half_vector 类型的别名

可通过 length 选项指定向量维度数量:

@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number

// Vector without specified dimensions
@Column("vector")
embedding: number[] | Buffer

// Vector with 3 dimensions: vector(3)
@Column("vector", { length: 3 })
embedding_3d: number[] | Buffer

// Half-precision vector with 4 dimensions: halfvec(4) (works on PostgreSQL and SAP HANA only)
@Column("halfvec", { length: 4 })
halfvec_embedding: number[] | Buffer
}

注意

  • MariaDB/MySQL:向量支持始于 MariaDB 11.7 和 MySQL 9
  • Microsoft SQL Server:向量类型需 SQL Server 2025 (17.x) 或更高版本
  • PostgreSQL:向量列需安装 pgvector 扩展(提供数据类型和相似性运算符)
  • SAP HANA:向量列需 SAP HANA Cloud (2024Q1+) 及兼容的 @sap/hana-client 版本

空间列

Microsoft SQLServer、MySQL/MariaDB、PostgreSQL/CockroachDB 和 SAP HANA 都支持空间列。 TypeORM 对不同数据库的空间列支持略有差异,特别是各数据库的列名不同。

MS SQL、MySQL/MariaDB 和 SAP HANA 使用 知名文本(WKT) 格式的几何数据,因此空间列应标记为 string 类型。

import { Entity, PrimaryColumn, Column } from "typeorm"

@Entity()
export class Thing {
@PrimaryColumn()
id: number

@Column("point")
point: string

@Column("linestring")
linestring: string
}

...

const thing = new Thing()
thing.point = "POINT(1 1)"
thing.linestring = "LINESTRING(0 0,1 1,2 2)"

对于 Postgres/CockroachDB,请参考 Postgis 数据类型

列选项

列选项为实体列定义额外配置。 您可以在 @Column 中指定列选项:

@Column({
type: "varchar",
length: 150,
unique: true,
// ...
})
name: string;

ColumnOptions 中可用的选项列表:

  • type: ColumnType - 列类型(从前文列出的类型中选择)

  • name: string - 数据库表列名。默认从属性名生成,可自定义覆盖。

  • length: number - 列类型长度(例如创建 varchar(150) 需同时指定类型和长度)

  • onUpdate: string - ON UPDATE 触发器(仅 MySQL 支持)

  • nullable: boolean - 设置列在数据库中为 NULLNOT NULL(默认 nullable: false

  • update: boolean - 指示列值是否通过 "save" 操作更新。若为 false,则仅在首次插入对象时可写入。默认值 true

  • insert: boolean - 指示列值是否在首次插入对象时设置。默认值 true

  • select: boolean - 定义默认查询时是否隐藏该列。设为 false 时,标准查询将不返回此列数据。默认为 select: true

  • default: string - 数据库级别的列默认值(DEFAULT)。

  • primary: boolean - 将列标记为主列(等效于使用 @PrimaryColumn)。

  • unique: boolean - 将列标记为唯一列(创建唯一约束)。

  • comment: string - 数据库列注释(并非所有数据库类型都支持)。

  • precision: number - 十进制(精确数值)列的精度(仅适用于 decimal 列),表示存储数值的最大位数。用于某些列类型。

  • scale: number - 十进制(精确数值)列的小数位数(仅适用于 decimal 列),表示小数点右侧的位数且不得超过精度值。用于某些列类型。

  • unsigned: boolean - 为数值列添加 UNSIGNED 属性(仅 MySQL 支持)。

  • charset: string - 定义列字符集(并非所有数据库类型都支持)。

  • collation: string - 定义列排序规则。

  • enum: string[]|AnyEnum - 用于 enum 列类型,指定允许的枚举值列表。可传入值数组或枚举类。

  • enumName: string - 定义所用枚举的名称。

  • asExpression: string - 生成列表达式(仅 MySQL 支持)。

  • generatedType: "VIRTUAL"|"STORED" - 生成列类型(仅 MySQL 支持)。

  • hstoreType: "object"|"string" - HSTORE 列返回类型(返回字符串或对象,仅 Postgres 支持)。

  • array: boolean - 用于可定义为数组的 Postgres 和 CockroachDB 列类型(如 int[])。

  • transformer: { from(value: DatabaseType): EntityType, to(value: EntityType): DatabaseType } - 用于将任意类型 EntityType 的属性序列化为数据库支持的 DatabaseType 类型。支持传入转换器数组,写入时按自然顺序应用,读取时按反向顺序应用(例如 [lowercase, encrypt] 会在写入时先转小写再加密,读取时先解密后不做处理)。

  • utc: boolean - 指示日期值是否应以 UTC 时区(而非本地时区)存储和检索(仅适用于 date 列类型)。默认值 false(为保持向后兼容使用本地时区)。

注意:多数列选项是关系型数据库特有的,在 MongoDB 中不可用。

实体继承

通过实体继承可减少代码重复。

例如,你有 PhotoQuestionPost 实体:

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

@Column()
title: string

@Column()
description: string

@Column()
size: string
}

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

@Column()
title: string

@Column()
description: string

@Column()
answersCount: number
}

@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number

@Column()
title: string

@Column()
description: string

@Column()
viewCount: number
}

可见这些实体都包含公共列:idtitledescription。为减少重复并提升抽象层次,可创建名为 Content 的基类:

export abstract class Content {
@PrimaryGeneratedColumn()
id: number

@Column()
title: string

@Column()
description: string
}
@Entity()
export class Photo extends Content {
@Column()
size: string
}

@Entity()
export class Question extends Content {
@Column()
answersCount: number
}

@Entity()
export class Post extends Content {
@Column()
viewCount: number
}

父实体中的所有列(关联关系、嵌入对象等,父实体也可继承其他实体)都将被继承并最终体现在实体中。

树形结构实体

TypeORM 支持两种树形结构存储模式:邻接列表和闭包表。

邻接列表

邻接列表是简单的自引用模型,优势在于实现简单,劣势是由于连接限制无法一次性加载大型树结构。示例:

import {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
OneToMany,
} from "typeorm"

@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@Column()
description: string

@ManyToOne((type) => Category, (category) => category.children)
parent: Category

@OneToMany((type) => Category, (category) => category.parent)
children: Category[]
}

闭包表

闭包表将父子关系存储在独立表中,读写效率俱佳。详细原理可参考 Bill Karwin 的精彩演示。示例:

import {
Entity,
Tree,
Column,
PrimaryGeneratedColumn,
TreeChildren,
TreeParent,
TreeLevelColumn,
} from "typeorm"

@Entity()
@Tree("closure-table")
export class Category {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@Column()
description: string

@TreeChildren()
children: Category[]

@TreeParent()
parent: Category

@TreeLevelColumn()
level: number
}