NestJS 实战:TypeORM 从入门到精通(完整教程)

在使用 NestJS 开发后端服务时,数据库操作是必不可少的环节。

TypeORM 是一个功能强大的 ORM 框架,完美支持 TypeScript,并且与 NestJS 深度集成,是官方首选的数据访问解决方案。

本篇文章带你从 0 到 1 掌握 NestJS + TypeORM,包含配置、实体定义、CRUD、事务、数据库迁移等企业级实战内容。

TypeORM 简介

ypeORM 是 Object-Relational Mapping(对象关系映射) 库,用于将 JavaScript/TypeScript 对象映射到数据库表结构,让我们可以用面向对象的方式操作数据库,不用手写大量 SQL 语句。

支持数据库:

● MySQL、PostgreSQL、SQLite

● SQL Server、Oracle

● MongoDB(NoSQL)

核心特性

● ✅ 支持 TypeScript 装饰器语法

● ✅ 支持 Active Record / Data Mapper 模式

● ✅ 自动同步表结构(开发环境)

● ✅ 强大的查询构建器

● ✅ 支持事务、迁移、关联查询

● ✅ 与 NestJS 无缝集成

安装依赖

确保已安装 NestJS 和 TypeORM 核心包:

bash 复制代码
npm install @nestjs/typeorm typeorm mysql2

根据使用的数据库选择对应的驱动(如 PostgreSQL 使用 pg)。

配置 TypeORM 模块

在 NestJS 应用的主模块中导入 TypeOrmModule 并配置数据库连接:

typescript 复制代码
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'password',
      database: 'test',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
  ],
})
export class AppModule {}

创建实体

定义 TypeORM 实体类,使用装饰器标记字段和关系,通过装饰器定义数据库表结构:

typescript 复制代码
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

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

  @Column()
  name: string;

  @Column()
  email: string;
}

注册实体与仓库

在特性模块中通过 TypeOrmModule.forFeature() 注册实体,自动生成 Repository:

typescript 复制代码
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [UserService],
})
export class UserModule {}

使用 Repository

通过依赖注入在服务层使用 Repository:

typescript 复制代码
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}

  findAll(): Promise<User[]> {
    return this.userRepository.find();
  }
}

事务管理

使用 @Transaction@TransactionManager 装饰器管理事务:

typescript 复制代码
import { Transaction, TransactionManager } from 'typeorm';

async createUser(userData: Partial<User>) {
  return this.userRepository.manager.transaction(async manager => {
    const user = manager.create(User, userData);
    return manager.save(user);
  });
}

迁移与 CLI

TypeORM 提供命令行工具生成和管理迁移:

bash 复制代码
typeorm migration:create -n UserMigration
typeorm migration:run

在 NestJS 中可通过配置 cli.entitiesDircli.migrationsDir 路径。

高级特性

  • 多数据库连接 :通过 TypeOrmModule.forRoot()name 属性支持多连接
  • 订阅者 :实现 EntitySubscriberInterface 监听实体事件
  • 查询构建器 :使用 createQueryBuilder() 进行复杂查询

通过以上步骤,可在 NestJS 应用中高效集成 TypeORM,实现完整的数据访问层。注意生产环境应关闭 synchronize 选项,改用迁移管理数据库结构变更。

synchronize 使用解析

在 TypeORM 中, synchronize: true 选项的作用是在应用启动时自动同步实体定义和数据库表结构。虽然这个选项在开发阶段非常方便,但在生产环境中必须关闭,主要原因如下:

生产环境关闭 synchronize: true 的原因

  1. 数据丢失风险 :

    • 当实体定义发生变化时(如删除字段、修改类型),TypeORM 会自动修改表结构
    • 这可能导致现有数据被删除或类型转换错误,造成不可挽回的数据损失
  2. 性能问题 :

    • 每次应用启动时,TypeORM 都会扫描所有实体并与数据库表结构进行比较
    • 在大型应用中,这会显著增加启动时间,影响服务可用性
  3. 不可控性 :

    • 自动同步可能会产生意外的表结构变更
    • 无法预览或验证变更的影响,增加了生产环境的风险
  4. 版本控制缺失 :

    • 自动同步的变更无法被版本控制系统跟踪
    • 难以回滚错误的变更或查看变更历史
  5. 生产环境稳定性 :

    • 生产环境需要严格的变更管理流程
    • 数据库结构变更应该经过测试和审批,而不是自动执行

生产环境的替代方案

在生产环境中,应该使用 数据库迁移(Migrations) 来管理表结构变更:

  1. 创建迁移文件 :

    复制代码
    pnpm run typeorm migration:create 
    --name=CreateUsersTable
  2. 编写迁移逻辑 :

    复制代码
    // migrations/
    1620000000000-CreateUsersTable.ts
    import { MigrationInterface, 
    QueryRunner } from 'typeorm';
    
    export class 
    CreateUsersTable1620000000000 
    implements MigrationInterface {
      public async up(queryRunner: 
      QueryRunner): Promise<void> {
        await queryRunner.query(`
          CREATE TABLE users (
            id INT PRIMARY KEY 
            AUTO_INCREMENT,
            name VARCHAR(255) NOT NULL,
            email VARCHAR(255) UNIQUE NOT 
            NULL
          )
        `);
      }
    
      public async down(queryRunner: 
      QueryRunner): Promise<void> {
        await queryRunner.query(`DROP TABLE 
        users`);
      }
    }
  3. 执行迁移 :

    复制代码
    pnpm run typeorm migration:run
  4. 回滚迁移 (如有必要):

    复制代码
    pnpm run typeorm migration:revert
相关推荐
网络点点滴4 小时前
简述Node.js运行时核心架构
架构·node.js
小粉粉hhh5 小时前
Node.js(三)——模块化
node.js
晓杰'5 小时前
从0到1实现 Balatro 游戏后端(1):项目规划与牌型判断实现
后端·websocket·typescript·node.js·游戏开发·项目实战·nestjs
@PHARAOH6 小时前
WHAT - npm和corepack
前端·npm·node.js
MPGWJPMTJT6 小时前
从 Volta 迁移到 mise:Windows 下 Node 版本管理切换记录
前端·node.js
zhangfeng11336 小时前
Remotion 渲染视频脚本 ,自动化编辑视频 Node.js 层面是“单线程 JS”,但在实际渲染时是“高度并行”的。
node.js·自动化·音视频
羽师7 小时前
Node.js和npx关系
node.js
灵魂学者7 小时前
使用 Electron 打包项目构建 .EXE 桌面应用程序(简)
electron·node.js·vue·build·桌面应用程序
右耳朵猫AI7 小时前
Node.js技术周刊 2026年第14周
node.js
gogoing21 小时前
Node.js 模块查找策略(require 完整流程)
javascript·node.js