实体
本页面由 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/identity的int列。保存前无需手动赋值。
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.findOneBy 或 repository.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 列类型被 postgres 和 mysql 支持。有几种可能的列定义方式:
使用 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 在数据库中支持 vector 和 halfvec 两种列类型:
-
vector- 以 4 字节浮点数(单精度)存储向量:- MariaDB/MySQL:原生
vector类型 - Microsoft SQL Server:原生
vector类型 - PostgreSQL:通过
pgvector扩展提供的vector类型 - SAP HANA Cloud:
real_vector类型的别名
- MariaDB/MySQL:原生
-
halfvec- 以 2 字节浮点数(半精度)存储向量以节省内存:- PostgreSQL:通过
pgvector扩展提供的halfvec类型 - SAP HANA Cloud:
half_vector类型的别名
- PostgreSQL:通过
可通过 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- 设置列在数据库中为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- 将列标记为唯一列(创建唯一约束)。 -
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 中不可用。
实体继承
通过实体继承可减少代码重复。
例如,你有 Photo、Question、Post 实体:
@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
}
可见这些实体都包含公共列:id、title、description。为减少重复并提升抽象层次,可创建名为 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
}