TypeORM - 如何在生产模式下创建新表并自动运行迁移?

Posted

技术标签:

【中文标题】TypeORM - 如何在生产模式下创建新表并自动运行迁移?【英文标题】:TypeORM - How to create new table and run migration automatically in production mode? 【发布时间】:2019-10-30 05:42:07 【问题描述】:

我想在 mysql 中创建新表并在应用程序在生产模式下运行时自动运行 TypeORM 迁移。

注意:这个新表不是在生产模式下启动应用程序之前创建的。

根据Migration Documentation,需要使用typeorm migration:run命令来运行迁移。

由于我的新表仅在应用程序调用 CreateNewTableTimeStamp(inputTableName).up 时创建,此时它将触发在我的数据库中创建新表。

但我没有找到如何自动执行此迁移的解决方案,因为每次应用程序调用此方法创建新表时,我都无法手动运行 typeorm migration:run

这个表建好之后,我会往这个新表中写入新的数据。

有人可以帮忙解决这个问题吗?

谢谢。

我的新表格代码:

class CreateNewTableTimeStamp implements MigrationInterface  

  tableName: string;

  constructor (inputTableName: string) 
    this.tableName = inputTableName
  

  async up(queryRunner: QueryRunner): Promise<any> 
    await queryRunner.createTable(new Table(
          name: this.tableName,
          columns: [
              
                  name: "id",
                  type: "int",
                  isPrimary: true
              ,
              
                  name: "email",
                  type: "varchar",
              
          ]
      ), true)
  

  async down(queryRunner: QueryRunner): Promise<any> 
    const table = await queryRunner.getTable(this.tableName);
    await queryRunner.dropTable(this.tableName);
  

【问题讨论】:

我不建议从您的服务器代码运行迁移,它应该在使用 CLI 命令启动您的节点服务器之前完成。随着代码的发展,最好不要在代码和 SQL 迁移结构之间带来硬依赖,并且迁移应该始终是不可变的和重放的。我鼓励您生成原始 SQL 查询,这样就不会执行“代码”(想象一下 TypeOrm 改变了执行 queryRunner 的方式,您的迁移可能会根据 TypeOrm 的版本变得可变!)。 @zenbeni,感谢您的建议。将更改我的设计,不再从我的服务器代码进行迁移。 【参考方案1】:

运行

yarn typeorm migration:create -n users(table_name)

表格代码示例:

   import  MigrationInterface, QueryRunner, Table  from 'typeorm';

export class createUsers1585025619325 implements MigrationInterface 
  private table = new Table(
    name: 'users',
    columns: [
      
        name: 'id',
        type: 'integer',
        isPrimary: true,
        isGenerated: true, // Auto-increment
        generationStrategy: 'increment',
      ,
      
        name: 'email',
        type: 'varchar',
        length: '255',
        isUnique: true,
        isNullable: false,
      ,
      
        name: 'created_at',
        type: 'timestamptz',
        isNullable: false,
        default: 'now()',
      ,
      
        name: 'updated_at',
        type: 'timestamptz',
        isNullable: false,
        default: 'now()',
      ,
    ],
  );

  public async up(queryRunner: QueryRunner): Promise<any> 
    await queryRunner.createTable(this.table);
  
  public async down(queryRunner: QueryRunner): Promise<any> 
    await queryRunner.dropTable(this.table);
  

运行创建的迁移:

yarn typeorm migration:run

【讨论】:

这不是自动生成方法【参考方案2】:

对于希望为测试目的运行迁移的人: 不在生产环境中。

import 
  createConnection,
  ConnectionOptions,
  Connection,
 from 'typeorm';

import  YourEntity  from 'path/to/your/entity.ts';

const testConfig: ConnectionOptions = 
  type: 'mongodb',
  url: 'mongodb://localhost:27017',
  database: 'test',
  useUnifiedTopology: true,
  entities: [YourEntity],
  synchronize: true,
  migrations: ['migrations/*YourMigrations.ts'],
;

let connection: Connection;

connection = await createConnection( ...testConfig );
await connection.synchronize(true);

await connection.runMigrations(
 transaction: 'all',
);

运行使用:

node -r ts-node/register ./path/to/migrations.ts

node ./path/to/compiled/migrations.js

【讨论】:

这个解决方法看起来不错,但你能解释一下为什么在生产运行时同步数据库不是一个好的做法吗? 问题不在于同步生产中的数据。更多的是关于你想如何进行生产。这个脚本是关于手动更新迁移的——这意味着通过从终端调用脚本来更新数据库。我相信这必须使用以下方法完成: - 运行迁移的自动方式,将迁移信息存储在 db 中。 - 必须咨询您的 devops 团队希望如何处理对 DB 的更改。很多时候,不允许应用删除或创建集合/索引。【参考方案3】:

正如@zenbeni 在评论中提到的那样,不建议从您的服务器代码运行迁移,因为迁移应该始终是不可变的和重放的。

因此,我会更改我的设计,不再从我的服务器代码进行迁移。

【讨论】:

以上是关于TypeORM - 如何在生产模式下创建新表并自动运行迁移?的主要内容,如果未能解决你的问题,请参考以下文章

插入创建新表

使用 NestJS、TypeORM、GraphQL 更新具有实体之间关系的 PSQL 表

在R闪亮中动态创建表时出错

如何在 PL/SQL 中连接两个表而不创建新表

如何在生产模式下索引猫鼬字段,我为啥要禁用自动索引功能?

如果我在流式传输之前先删除表并创建表,Google BigQuery Streaming 有时会失败