在NestJS中创建生成并执行PostgreSQL的TypeORM Migration
@TOC
推荐超级课程:
您想使用TypeORM从实体创建、运行和生成 Migration吗?在这个Nest.js TypeORM Migration示例指南中,您将学到:
- 如何在NestJS中使用PostgreSQL创建TypeORM Migration
- 创建一个实体,TypeORM用来运行 Migration
- 创建TypeORM Migration的步骤
- 使用TypeORM生成 Migration
- 显示所有 Migration
- 应用 Migration
- 回滚和撤销 Migration
- 运行待处理的 Migration
- 了解TypeORM数据库同步
- 如何手动生成、运行和应用TypeORM NestJS Migration。
- 撤销上一个 Migration。
为什么不深入探讨这个指南,将您的TypeORM Migration推向一个新的高度呢?
先决条件
要在Nest.js中使用TypeORM Migration,请确保您具备以下内容:
- 在计算机上安装了Node.js 。
- 在计算机上安装了PostgreSQL 。
- 对使用NestJS和TypeORM有一些基本了解将是一个额外的优势。
配置TypeORM Migration实体与PostgreSQL
实体使用TypeORM需要创建数据库表(在运行NOSQL数据库时会创建集合)的类和装饰器。简化起见,实体定义了数据的模式和结构。
您的 Migration将使用一个实体,让TypeORM在您的PostgreSQL上完成它的工作。因此,要让TypeORM从实体生成 Migration,请按以下方式创建一个:
确保您已安装Nest.js CLI:
npm install -g @nestjs/cli
设置您的Nest.js应用程序:
nest new task_app_api
安装核心TypeORM Migration依赖项和pg 用于PostgreSQL包:
npm install --save @nestjs/typeorm typeorm @nestjs/config pg
准备好您的模块
nest g module task
nest g service task --no-spec
nest g controller task --no-spec
要配置一个实体,创建一个task.entity.ts
文件在src/task
目录中。此文件将承载tasks
表的配置。现在使用TypeORM实体表示您的 Migration表如下:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity("tasks")
export class Task {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
description: string;
@Column({ default: false })
isCompleted: boolean;
}
TypeORM将在您的模块中访问这个实体。转到src/task/task.module.ts
,按如下方式导入和配置TypeOrmModule
:
// 导入模块和组件
import { Module } from '@nestjs/common';
import { TaskService } from './task.service';
import { TaskController } from './task.controller';
// TypeOrmModule创建数据库集成
import { TypeOrmModule } from '@nestjs/typeorm';
// 您的Task实体类
import { Task } from './task.entity';
@Module({
// 创建一个导入模块
// 将TypeOrmModule添加到Task实体
imports: [TypeOrmModule.forFeature([Task])],
providers: [TaskService],
controllers: [TaskController]
})
export class TaskModule {}
配置TypeORM Migration的数据库同步
TypeORM决定您的表的结构。有两种方式可以做到这一点:
- 允许TypeORM自动填充您的表
- 生成并运行 Migration
您只需使用一个参数来控制TypeORM的工作方式,即synchronize
。如果为true
,TypeORM会自动填充您的表;如果为false
,TypeORM会查找 Migration的配置。
同步定义了当新列被添加到表中时模型的反应方式。在生产中不建议使用同步以避免丢失数据。要配置同步,请转到您的src/task
文件夹并创建一个data.source.ts
,使用如下数据源选项:
import { DataSource, DataSourceOptions } from 'typeorm';
export const dbdatasource: DataSourceOptions = {
// TypeORM PostgreSQL数据库驱动程序
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'pass',
// 数据库名称
database: 'task',
// 与实体同步数据库架构
synchronize: false,
};
const dataSource = new DataSource(dbdatasource)
export default dataSource
重点注意事项:
- 此文件被创建为
DataSource
。TypeORM CLI使用数据源API 实例作为实体管理器,以建立与您的数据库类型的连接。 - 确保您的PostgreSQL数据库属性与密码、用户名和数据库匹配。
- 添加您的实体以便TypeORM将其添加到您的数据库连接中以填充您的表。
synchronize: false,
是此处最关键的属性。由于您将运行 Migration,将其设置为false。
您必须准备这些并且最重要的是在此步骤中创建您的数据库。TypeORM不会创建数据库,它只处理您的表。
转到src/app.module.ts
并按以下方式使用DataSource
和数据库连接:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TaskModule } from './task/task.module';
// 导入dataSource类
import { dbdatasource } from './task/data.source';
// TypeOrmModule数据库集成
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot(dbdatasource),
TaskModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
设置TypeORM Migration路径
TypeORM CLI将查看您的数据源以确定如何运行您的 Migration。为了使TypeORM运行 Migration,它必须检查您要保存 Migration文件的实体和文件路径。因此,在这里我们需要添加以下参数:
// TypeORM实体
entities: ['build/task/task.entity.js'],
// 您的 Migration路径
migrations: ['build/task/migrations/*.js'],
这意味着您必须更新您的data.source.ts
文件如下:
import { DataSource, DataSourceOptions } from 'typeorm';
export const dbdatasource: DataSourceOptions = {
// TypeORM PostgreSQL数据库驱动程序
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'pass',
// 数据库名称
database: 'task',
// 与实体同步数据库架构
synchronize: false,
// TypeORM实体
entities: ['build/task/task.entity.js'],
// 您的 Migration路径
migrations: ['build/task/migrations/*.js'],
migrationsTableName: "task_migrations",
};
const dataSource = new DataSource(dbdatasource)
export default dataSource
entities
读取您的实体文件的路径。migrations
是您的 Migration文件将保存的目录。migrationsTableName
将在您的数据库中创建另一个表(task_migrations
)以保存TypeORM生成的所有 Migration。
请注意,TypeORM将从本示例中已转译为JavaScript的构建文件中读取。
因此,请确保上述路径是正确的。否则,您的 Migration将失败。在我的情况下,转译后的文件保存在
build
文件夹中。如果您有不同的转译配置目录,比如dist
,请相应地更新您的路径。
要确保,一个简单的方法是执行npm run build
。然后检查您的构建路径:
使用TypeORM CLI生成您的第一个TypeORM Migration
让TypeORM现在允许从实体生成 Migration几个命令。通常,您将使用以下命令格式生成Nest.js TypeORM Migration:
npx typeorm-ts-node migration:generate path-to-save-migrations/YourMigrationName -- -d path-to-datasource-configpath.ts
要创建上述命令示例,请转到您的package.json
文件,并添加一个用于生成 Migration的脚本,如下所示:
"typeorm": "npm run build && npx typeorm -d build/task/data.source.js",
"migration:generate": "npm run typeorm -- migration:generate",
第一个命令表示npx typeorm
。它会构建您的项目npm run build
,确保首先将typescript转译为JavaScript,然后再运行您的 Migration。请注意。相同的命令具有标志-d
,该标志会执行您的数据源,且您必须提供它的路径作为参数,如build/task/data.source.js
,因此请确保您的路径正确。
TypeORM CLI将执行npm run typeorm -- migration:generate
来生成 Migration。在这种情况下,您必须提供保存文件的路径。
因此运行以下命令:
npm run migration:generate -- src/task/migrations/task
TypeORM将在这种情况下在src/task
目录中创建一个migrations
文件夹。 Migration将被命名为task
。
此路径应与您添加的migrations: ['build/task/migrations/*.js']
相同。其中*.js
将是 Migration文件。
如果您转到相同的路径,您的 Migration将被创建如下:
import { MigrationInterface, QueryRunner } from "typeorm";
export class Task1696512256621 implements MigrationInterface {
name = 'Task1696512256621'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "tasks" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "description" character varying NOT NULL, "isCompleted" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_8d12ff38fcc62aaba2cab748772" PRIMARY KEY ("id"))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "tasks"`);
}
}
运行您的Nest.js TypeORM Migration
要将上述查询应用到您的数据库,请将以下命令添加到您的package.json
脚本中:
"typeorm": "npm run build && npx typeorm -d build/task/data.source.js",
"migration:generate": "npm run typeorm -- migration:generate",
"migration:run": "npm run typeorm -- migration:run",
现在运行以下命令:
npm run migration:run
TypeORM将运行您的 Migration并告诉您,Migration Task1696521113842 has been executed successfully
。在这种情况下,您将有两个表:
- 从您的实体执行的Tasks
- 由TypeORM CLI创建的Task_migrations用于保存您的 Migration,正如您在
migrationsTableName: "task_migrations"
中指定的那样
检查这些表在您的数据库上:
在此时,我们的 Migration已经部署。如果您尝试运行生成命令:
npm run migration:generate -- src/task/migrations/task
TypeORM将给出信号:
显示所有 Migration
要检查可用的 Migration,将以下脚本添加到package.json
文件中:
"migration:show": "npm run typeorm -- migration:show",
然后运行以下命令:
npm run migration:show
运行待处理的 Migration
假设您已更改了您的实体,例如添加了一个新字段。在这种情况下,重新生成 Migration:
npm run migration:generate -- src/task/migrations/task
然后再次应用它们:
npm run migration:show
回滚和撤销TypeORM Migration
如果您想要返回到以前的 Migration,您的task_migrations
表会保存可用的 Migration记录,您可以像下面这样撤销:
"migration:revert": "npm run typeorm -- migration:revert",
运行您的回滚命令如下:
如何手动生成和创建TypeORM Nest.js Migration
到目前为止,您已经学会使用TypeORM CLI自动生成、创建和运行您的 Migration。
但是,您可以选择手动运行您的 Migration,这一部分将教您如何这样做。
这使用TypeORM MigrationAPI编写 Migration 作为手动创建 Migration文件的方法。
在这里,您必须使用MigrationBuilder
来为up
和down
方法创建SQL查询。
up
- 用于执行 Migration的查询。down
- 执行SQL查询以撤消 Migration。
为此,您首先会运行TypeORM Migration命令如下:
npx typeorm migration:create src/task/migrations/task
src/task/migrations/task
保持不变。
此命令应该生成带有up
和down
方法的 Migration文件,如下所示:
import { MigrationInterface, QueryRunner } from "typeorm"
export class Task1696523336681 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
}
public async down(queryRunner: QueryRunner): Promise<void> {
}
}
up
方法将更新如下:
- 更新导入,以便TypeORM可以创建表
import { MigrationInterface, Table, QueryRunner } from "typeorm"
- 创建一个
queryRunner
,其中名称是您的数据库表,列是表字段,如下:
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(new Table({
name: "tasks",
columns: [
{
name: "id",
type: "serial",
isPrimary: true,
isNullable: false,
},
{
name: "title",
type: "varchar",
isNullable: false,
},
{
name: "description",
type: "varchar",
isNullable: false,
},
{
name: "isCompleted",
type: "boolean",
isNullable: false,
default: false,
},
],
}), true);
}
这是一个简单易懂的查询例子。例如,字段title
是一个varchar,不能为NULL。
TypeORM 将使用 down
方法来启动一个回滚命令。所以,它将执行一个 dropTable
查询如下:
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("tasks");
}
现在运行 Migration并使用 Migration运行命令将更改应用到你的数据库:
npm run migration:run
如果你想要启动一个回滚,运行你的回滚命令:
npm run migration:revert
结论
在本 Nest.js TypeORM Migration示例指南中,你学会了:
- 如何在 NestJS 中使用 PostgreSQL 创建 TypeORM Migration
- 创建一个 TypeORM 用于运行 Migration的实体
- 创建 TypeORM Migration的步骤
- 使用 TypeORM 生成 Migration
- 显示、运行和回滚 Migration
- 理解 TypeORM 数据库同步
- 如何手动生成、运行和应用 TypeORM NestJS Migration。
希望你觉得这个指南有帮助。