TypeORM 是一个基于 TypeScript/JavaScript 的对象关系映射(ORM)框架 ,支持 Node.js、浏览器等多平台,可对接 MySQL、PostgreSQL、SQLite、SQL Server 等主流数据库。其核心设计理念是"让开发者用面向对象的方式操作数据库",通过装饰器或实体类定义数据模型,自动生成 SQL 并管理数据库交互。以下基于 TypeORM v0.3.x(最新稳定版)官方文档,详细介绍其用法。

https://github.com/typeorm/typeorm
一、核心概念与设计模式
TypeORM 支持两种编程模式:
- Active Record :实体类直接包含 CRUD 方法(如
save()、remove()),适合简单场景。 - Data Mapper :实体类仅定义数据结构,通过
Repository或EntityManager执行操作,适合复杂业务逻辑(推荐)。
二、安装与环境准备
1. 基础依赖安装
bash
# 安装 TypeORM 核心库
npm install typeorm reflect-metadata --save
# 安装数据库驱动(根据使用的数据库选择)
# MySQL/MariaDB
npm install mysql2 --save
# PostgreSQL
npm install pg --save
# SQLite
npm install sqlite3 --save
# SQL Server
npm install tedious --save
2. TypeScript 配置(关键!)
在 tsconfig.json 中启用装饰器支持:
json
{
"compilerOptions": {
"experimentalDecorators": true, // 启用装饰器
"emitDecoratorMetadata": true, // 允许反射元数据(TypeORM 依赖)
"target": "ES2020",
"module": "CommonJS"
}
}



三、核心用法详解
1. 定义实体(Entity)
实体是映射到数据库表的类,通过装饰器 @Entity() 标记,字段用 @Column() 定义。
示例:用户实体(User)
typescript
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm";
@Entity("users") // 映射到数据库表名(默认类名小写复数,此处显式指定)
export class User {
@PrimaryGeneratedColumn() // 自增主键(等价于 AUTO_INCREMENT)
id: number;
@Column({ length: 50, unique: true }) // 字符串列,长度50,唯一约束
username: string;
@Column({ select: false }) // 查询时默认不返回该字段(如密码)
password: string;
@Column({ type: "int", default: 0 }) // 整数列,默认值0
age: number;
@Column({ type: "boolean", default: true }) // 布尔列,默认值true
isActive: boolean;
@Column({ type: "timestamp", nullable: true }) // 时间戳列,可为空
lastLoginAt: Date;
@CreateDateColumn() // 自动记录创建时间(无需手动赋值)
createdAt: Date;
@UpdateDateColumn() // 自动记录更新时间(更新时自动刷新)
updatedAt: Date;
}
常用列装饰器参数:
type:数据库类型(如"varchar"、"int"、"boolean"、"timestamp"),默认根据属性类型推断。length:字符串长度(如{ length: 255 })。nullable:是否允许 NULL(默认false)。default:默认值(如{ default: "active" })。unique:是否唯一约束(如{ unique: true })。
2. 定义关系(Relationships)
TypeORM 支持 一对一(@OneToOne)、一对多(@OneToMany)、多对多(@ManyToMany) 关系,通过外键或中间表关联。
示例:用户(User)与文章(Post)的一对多关系
typescript
// post.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { User } from "./user.entity";
@Entity("posts")
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column("text")
content: string;
// 多对一:多个 Post 属于一个 User(外键 userId)
@ManyToOne(() => User, (user) => user.posts, {
onDelete: "CASCADE" // 用户删除时,级联删除其所有文章
})
user: User; // 关联的用户对象(查询时可加载)
@Column() // 显式存储外键(可选,TypeORM 会自动维护)
userId: number;
}
// 更新 User 实体,添加反向关联(一对多)
// user.entity.ts
import { Post } from "./post.entity";
@Entity("users")
export class User {
// ... 其他字段 ...
@OneToMany(() => Post, (post) => post.user) // 一个 User 有多个 Post
posts: Post[]; // 用户的文章列表(查询时可加载)
}
关系核心参数:
target:关联的实体类(如() => User)。inverseSide:反向关联的属性(如(user) => user.posts,表示 User 类中关联 Post 的字段)。onDelete:级联删除策略("CASCADE"/"SET NULL"/"RESTRICT")。

3. 创建数据库连接
TypeORM v0.3.x 推荐使用 DataSource 类管理连接(替代旧版 createConnection)。
示例:创建 MySQL 连接
typescript
import { DataSource } from "typeorm";
import { User } from "./entity/User";
import { Post } from "./entity/Post";
const AppDataSource = new DataSource({
type: "mysql", // 数据库类型
host: "localhost",
port: 3306,
username: "root",
password: "password",
database: "test_db",
synchronize: true, // 开发环境自动同步实体到数据库(生产环境禁用!)
logging: ["error", "warn"], // 日志级别
entities: [User, Post], // 注册的实体类
migrations: [], // 迁移文件(见下文)
subscribers: [], // 订阅者(事件监听)
});
// 初始化连接
AppDataSource.initialize()
.then(() => console.log("数据库连接成功"))
.catch((error) => console.error("连接失败", error));
关键参数说明:
synchronize: true:自动根据实体定义创建/更新表结构(仅开发环境使用,生产环境需用迁移)。entities:数组形式注册实体类(也可通过 glob 路径加载,如[__dirname + "/entity/*.ts"])。
4. CRUD 操作(基于 Repository)
通过 DataSource.getRepository(Entity) 获取实体的 Repository,执行 CRUD。
示例:User 实体的 CRUD
typescript
// 假设已初始化 AppDataSource
const userRepository = AppDataSource.getRepository(User);
// 1. 创建(新增)用户
async function createUser() {
const user = new User();
user.username = "john_doe";
user.password = "hashed_password"; // 实际需加密
user.age = 30;
await userRepository.save(user); // 保存到数据库
console.log("用户创建成功,ID:", user.id);
}
// 2. 查询用户
async function getUsers() {
// 查询所有用户(排除 password 字段,因 @Column({ select: false }))
const allUsers = await userRepository.find();
// 条件查询:年龄 > 25 且激活状态
const activeUsers = await userRepository.find({
where: { age: MoreThan(25), isActive: true }, // MoreThan 需导入:import { MoreThan } from "typeorm"
order: { createdAt: "DESC" }, // 按创建时间倒序
take: 10, // 限制返回10条
});
// 查询单个用户(按 ID)
const user = await userRepository.findOneBy({ id: 1 });
// 关联查询:加载用户的文章(posts 字段)
const userWithPosts = await userRepository.findOne({
where: { id: 1 },
relations: ["posts"], // 加载关联的 posts 字段
});
}
// 3. 更新用户
async function updateUser(id: number) {
const user = await userRepository.findOneBy({ id });
if (user) {
user.age = 31;
user.isActive = false;
await userRepository.save(user); // 保存更新
// 或直接更新部分字段(无需先查询)
await userRepository.update(id, { age: 31, isActive: false });
}
}
// 4. 删除用户
async function deleteUser(id: number) {
// 软删除(推荐,需配合 @DeleteDateColumn)
// 硬删除(物理删除)
await userRepository.delete(id);
}
常用查询方法:
find(options):查询多条,options含where/order/take/skip/relations。findOne(options):查询单条,options.where可传对象或表达式。findOneBy(where):简化版单条查询(仅where条件)。save(entity):新增或更新(若实体有id则更新)。update(where, partialEntity):批量更新符合条件的记录。delete(where):删除符合条件的记录。
5. 高级特性
(1)迁移(Migrations)
迁移用于版本控制数据库结构 ,替代 synchronize: true(生产环境必备)。
步骤:
-
生成迁移文件:
bashnpx typeorm-ts-node-commonjs migration:generate -d src/migrations/Datasource src/migrations/InitUsersTable生成的文件位于
src/migrations,包含up(执行变更)和down(回滚变更)方法。 -
编辑迁移文件(示例:创建 users 表):
typescriptimport { MigrationInterface, QueryRunner } from "typeorm"; export class InitUsersTable1700000000000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(` CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, age INT DEFAULT 0, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) `); } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`DROP TABLE users`); } } -
执行迁移:
bashnpx typeorm-ts-node-commonjs migration:run -d src/migrations/Datasource -
回滚迁移:
bashnpx typeorm-ts-node-commonjs migration:revert -d src/migrations/Datasource
(2)事务(Transactions)
通过 EntityManager 或 Repository.manager 开启事务,确保多步操作的原子性。
示例:转账事务(用户A扣钱,用户B加钱)
typescript
async function transferMoney(fromId: number, toId: number, amount: number) {
return AppDataSource.manager.transaction(async (transactionalEntityManager) => {
// 1. 查询用户A(加锁防止并发问题)
const fromUser = await transactionalEntityManager.findOneBy(User, { id: fromId }, { lock: { mode: "pessimistic_write" } });
if (!fromUser || fromUser.balance < amount) throw new Error("余额不足");
// 2. 查询用户B
const toUser = await transactionalEntityManager.findOneBy(User, { id: toId });
if (!toUser) throw new Error("目标用户不存在");
// 3. 执行转账
fromUser.balance -= amount;
toUser.balance += amount;
await transactionalEntityManager.save([fromUser, toUser]);
});
}
(3)查询构建器(QueryBuilder)
用于复杂查询(如联表、子查询、聚合函数),支持链式调用。
示例:查询"用户及其最近3篇文章"
typescript
const userWithRecentPosts = await userRepository
.createQueryBuilder("user") // 别名 "user"
.leftJoinAndSelect("user.posts", "post") // 联表并加载 posts,别名为 "post"
.where("user.id = :id", { id: 1 }) // 条件:用户ID=1
.orderBy("post.createdAt", "DESC") // 按文章创建时间倒序
.take(3) // 取3篇
.getOne(); // 获取单条结果
常用方法:
createQueryBuilder(alias):创建构建器,指定主表别名。leftJoinAndSelect(relation, alias):左联并加载关联表。where(condition, parameters):添加 WHERE 条件。andWhere(condition):追加 AND 条件。orderBy(field, direction):排序。getOne()/getMany():执行查询并返回单条/多条结果。
(4)软删除(Soft Delete)
通过 @DeleteDateColumn() 标记删除时间字段,删除时仅更新该字段(而非物理删除)。
示例:
typescript
@Entity()
export class User {
// ... 其他字段 ...
@DeleteDateColumn({ name: "deleted_at" }) // 软删除标记(默认列名 deletedAt)
deletedAt: Date | null;
}
// 使用:软删除用户
await userRepository.softDelete(1); // 设置 deletedAt 为当前时间
// 查询时排除已软删除的记录(默认行为)
const activeUsers = await userRepository.find();
// 包含已软删除的记录
const allUsers = await userRepository.find({ withDeleted: true });
四、完整示例:用户-文章系统
1. 实体定义
typescript
// user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, OneToMany, DeleteDateColumn } from "typeorm";
import { Post } from "./post.entity";
@Entity("users")
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 50, unique: true })
username: string;
@Column({ select: false })
password: string;
@Column({ type: "int", default: 0 })
age: number;
@Column({ type: "boolean", default: true })
isActive: boolean;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@DeleteDateColumn()
deletedAt: Date;
@OneToMany(() => Post, (post) => post.user)
posts: Post[];
}
// post.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { User } from "./user.entity";
@Entity("posts")
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column("text")
content: string;
@ManyToOne(() => User, (user) => user.posts, { onDelete: "CASCADE" })
user: User;
@Column()
userId: number;
}
2. 数据库连接与 CRUD
typescript
import "reflect-metadata";
import { DataSource } from "typeorm";
import { User } from "./entity/user.entity";
import { Post } from "./entity/post.entity";
const AppDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "password",
database: "test_db",
synchronize: true, // 开发环境临时使用
entities: [User, Post],
});
AppDataSource.initialize().then(async () => {
const userRepo = AppDataSource.getRepository(User);
const postRepo = AppDataSource.getRepository(Post);
// 创建用户
const user = new User();
user.username = "alice";
user.password = "pass123";
user.age = 28;
await userRepo.save(user);
// 创建文章
const post = new Post();
post.title = "Hello TypeORM";
post.content = "TypeORM is awesome!";
post.user = user; // 关联用户
post.userId = user.id;
await postRepo.save(post);
// 查询用户及其文章
const result = await userRepo.findOne({
where: { id: user.id },
relations: ["posts"],
});
console.log(result); // { id: 1, username: 'alice', ..., posts: [{ id: 1, title: 'Hello TypeORM', ... }] }
});
五、注意事项
- 生产环境禁用
synchronize: true:改用迁移(Migrations)管理表结构变更。 - 性能优化 :避免 N+1 查询(通过
relations或join预加载关联数据)。 - 事务使用:涉及多表修改时必须用事务保证一致性。
- 类型安全:优先使用 TypeScript 类型定义实体,减少运行时错误。
- 官方文档:始终参考 https://typeorm.io/(最新版)获取细节。
通过以上内容,可掌握 TypeORM 的核心用法。实际开发中需结合业务场景选择合适的模式(Active Record/Data Mapper),并充分利用其关系映射、迁移、事务等特性构建健壮的数据层。