实体(Entity)核心教程
原创2026/3/18大约 5 分钟
一、实体基础定义
实体(Entity)是 TypeORM 中映射数据库表的核心载体,本质是被装饰器标记的 TypeScript 类,每个实体实例对应数据库表中的一行数据,实体类的属性对应表的字段。
1. 基础实体定义(@Entity 装饰器)
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm";
// 基础定义:默认表名为类名小写(如当前类名 User → 表名 user)
@Entity()
export class User {
// 自增主键(TypeORM 自动适配数据库自增策略)
@PrimaryGeneratedColumn()
id: number;
// 普通字符串字段(默认映射为 varchar(255))
@Column()
username: string;
// 带自定义配置的字段
@Column({
length: 100, // 字段长度
nullable: false, // 非空约束(默认值为 false)
default: "未知用户", // 默认值
comment: "用户昵称" // 数据库字段注释
})
nickname: string;
@Column({ type: "int", default: 0 })
age: number;
}2. 自定义表名
通过 @Entity 装饰器的参数可自定义表名,还支持多数据库/模式适配:
// 直接指定表名
@Entity("sys_user") // 映射到数据库的 sys_user 表
export class User {
// ... 字段定义
}
// 多数据库/模式适配(PostgreSQL 常用)
@Entity({
name: "sys_user", // 表名
database: "test_db", // 指定所属数据库(多库场景)
schema: "public" // PostgreSQL 模式(默认 public)
})
export class User {
// ... 字段定义
}二、字段装饰器详解
1. 主键装饰器
主键是表的唯一标识,TypeORM 提供两种核心主键装饰器,满足不同场景需求:
| 装饰器 | 核心说明 |
|---|---|
| @PrimaryColumn | 手动指定主键(非自增),支持 int、uuid、string 等任意类型 |
| @PrimaryGeneratedColumn | 自增主键,自动适配数据库策略(MySQL:AUTO_INCREMENT;PostgreSQL:serial) |
示例:
import { Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Product {
// 手动指定 UUID 主键(需自己生成 UUID 赋值)
@PrimaryColumn({ type: "uuid" })
productId: string;
// 自动生成 UUID 主键(无需手动赋值)
@PrimaryGeneratedColumn("uuid")
id: string;
// MySQL 无符号自增主键
@PrimaryGeneratedColumn({ type: "int", unsigned: true })
sid: number;
}2. 普通字段装饰器(@Column)
@Column 是最常用的字段装饰器,支持丰富的配置项,覆盖大部分数据库字段特性:
@Column({
type: "varchar", // 数据库字段类型(可选,TS类型自动映射)
name: "user_name", // 数据库字段名(默认与属性名一致)
length: 50, // 长度(仅字符串类型生效)
nullable: true, // 是否允许为空(默认 false)
unique: true, // 是否添加唯一索引
default: "guest", // 数据库默认值
comment: "用户名", // 字段注释
unsigned: true, // 是否无符号(仅数值类型,MySQL 专属)
select: true, // 查询时是否默认返回(false 需手动指定查询)
zerofill: false, // 零填充(仅数值类型,MySQL 专属)
collation: "utf8mb4_general_ci" // 字符集排序规则(MySQL 专属)
})
username: string;3. 特殊业务字段装饰器
TypeORM 内置了常用业务字段的装饰器,简化时间、软删除、乐观锁等场景的开发:
import { CreateDateColumn, UpdateDateColumn, DeleteDateColumn, VersionColumn } from "typeorm";
@Entity()
export class Order {
@PrimaryGeneratedColumn()
id: number;
@CreateDateColumn({ comment: "订单创建时间" }) // 自动赋值创建时间
createTime: Date;
@UpdateDateColumn({ comment: "订单更新时间" }) // 自动更新修改时间
updateTime: Date;
@DeleteDateColumn({ comment: "删除时间(软删除)" }) // 软删除标记字段
deleteTime: Date;
@VersionColumn({ comment: "版本号(乐观锁)" }) // 乐观锁,更新时自动递增
version: number;
}三、TS 类型 ↔ 数据库类型映射
TypeScript 类型会自动映射为对应数据库字段类型,不同数据库的映射规则略有差异(以下为 MySQL 基准映射):
| TypeScript 类型 | 默认 MySQL 类型 | 可选扩展类型 |
|---|---|---|
| string | varchar(255) | char、text、longtext、json |
| number | int | tinyint、bigint、float、double |
| boolean | tinyint(1) | boolean(PostgreSQL 专属) |
| Date | datetime | timestamp、date、time |
| object/any | json | jsonb(PostgreSQL 专属) |
手动指定字段类型示例(覆盖自动映射):
@Entity()
export class Article {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: "longtext" }) // 长文本,适配大篇幅内容
content: string;
@Column({ type: "bigint" }) // 大整数,适配海量数据ID/金额
viewCount: number;
@Column({ type: "json" }) // JSON 类型,存储复杂结构化数据
metaInfo: { author: string; tags: string[]; readTime: number };
@Column({ type: "date" }) // 仅日期类型(不含时间)
publishDate: Date;
}四、实体选项
1. 禁用列(忽略属性)
若属性仅用于内存计算,无需映射到数据库,可通过以下方式忽略:
import { Entity, Column, Ignore } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ select: false }) // 查询时默认不返回(如密码字段)
password: string;
@Ignore() // 完全忽略,不映射到数据库表
tempAccessToken: string; // 仅内存使用,不入库
}2. 软删除基础配置
软删除不会物理删除数据,仅通过 @DeleteDateColumn 标记删除时间,查询时 TypeORM 会自动过滤已删除数据:
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@DeleteDateColumn() // 软删除字段,删除时自动填充当前时间
deletedAt: Date;
}
// 软删除相关操作示例
```typescript
// 软删除单条数据
await userRepository.softRemove(user);
// 按ID软删除
await userRepository.softDelete(1);
// 恢复软删除数据
await userRepository.restore(1);
// 默认查询:仅返回未删除数据
const activeUsers = await userRepository.find();
// 查询包含软删除的数据
const allUsers = await userRepository.find({ withDeleted: true });
// 仅查询软删除的数据
import { Not, IsNull } from "typeorm";
const deletedUsers = await userRepository.find({
where: { deletedAt: Not(IsNull()) }
});3. 实体继承
TypeORM 支持单表继承和多表继承,核心解决“多个实体共享基础字段”的问题。
单表继承(推荐)
所有子类共享一张数据库表,通过「区分列」标识不同子类的记录:
import { Entity, Column, PrimaryGeneratedColumn, TableInheritance, DiscriminatorColumn, ChildEntity } from "typeorm";
// 父实体(基类)
@Entity()
@TableInheritance({ column: { name: "person_type" } }) // 区分列:person_type
@DiscriminatorColumn({ name: "person_type", type: "varchar" })
export class Person {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
age: number;
}
// 子实体:学生(继承 Person)
@ChildEntity("student") // 区分列值为 student
export class Student extends Person {
@Column({ nullable: true }) // 学生专属字段
studentId: string;
@Column({ nullable: true })
className: string;
}
// 子实体:教师(继承 Person)
@ChildEntity("teacher") // 区分列值为 teacher
export class Teacher extends Person {
@Column({ nullable: true }) // 教师专属字段
teacherId: string;
@Column({ nullable: true })
subject: string;
}多表继承
每个子类对应独立的数据库表,父类的字段会冗余到子类表中:
// 父实体(无 TableInheritance 装饰器)
@Entity()
export class Person {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}
// 子实体:学生(独立表)
@ChildEntity()
@Entity("student") // 显式指定子类表名
export class Student extends Person {
@Column()
studentId: string;
}
// 子实体:教师(独立表)
@ChildEntity()
@Entity("teacher") // 显式指定子类表名
export class Teacher extends Person {
@Column()
teacherId: string;
}至此,本章节的学习就到此结束了,如有疑惑,可对接技术客服进行相关咨询。