自从我升级到TypeORM 0.3以来,我面临着一个奇怪的错误,我生成了我的第一个迁移,因为数据库是空的,而且它是正确生成的。如果我在之后生成第二个迁移,而不对实体进行任何更改,则生成的迁移会识别每个表上的更改,使用类似的脚本
await queryRunner.query(`ALTER TABLE `clients` CHANGE `deletedAt` `deletedAt` datetime(6) NULL`);
await queryRunner.query(`ALTER TABLE `clients` CHANGE `type` `type` varchar(255) NULL`);
await queryRunner.query(`ALTER TABLE `clients` CHANGE `first_name` `first_name` varchar(255) NULL`);
await queryRunner.query(`ALTER TABLE `clients` CHANGE `last_name` `last_name` varchar(255) NULL`);
await queryRunner.query(`ALTER TABLE `clients` CHANGE `company_name` `company_name` varchar(255) NULL`);
await queryRunner.query(`ALTER TABLE `clients` CHANGE `administrator_name` `administrator_name` varchar(255) NULL`);
这只是第二次迁移的一些行,实际上我的所有表的列都是用ALTER TABLE CHANGE脚本在第二次移植中编写的,这很奇怪,因为我没有做任何更改。即使在接下来的迁移中,这些脚本也会继续显示。
预期行为
我希望只显示对实体所做的更改,而不是每次生成迁移时都显示每一列
package.json
"build": "tsc -p tsconfig.build.json",
"typeorm": "node -r ts-node/register ./node_modules/typeorm/cli.js -d src/ormconfig.ts",
"migration:revert": "npm run typeorm migration:revert",
"migration:run": "npm run build && npm run typeorm migration:run",
"migration:generate": "npm run build && npm run typeorm migration:generate",
ormconfig.ts
const ormconfiguration = {
type: getConnectionType(process.env.TYPEORM_CONNECTION),
host: process.env.TYPEORM_HOST,
port: Number(process.env.TYPEORM_PORT),
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
entities: [process.env.TYPEORM_ENTITIES],
migrations: [process.env.TYPEORM_MIGRATIONS],
},
.env
#APP_CONFIG
HOST=http://localhost:5000
NODE_ENV=development
#DATABASE
TYPEORM_CONNECTION=mysql
TYPEORM_HOST=db-dev
TYPEORM_USERNAME=root
TYPEORM_PASSWORD=admin321
TYPEORM_DATABASE=suitcase_db
TYPEORM_PORT=3306
TYPEORM_SYNCHRONIZE=false
TYPEORM_LOGGING=false
# TYPEORM_ENTITIES= ./src/entities/*.entity.ts
# TYPEORM_MIGRATIONS= ./src/migrations/*.ts
# for working with npm run start:dev
TYPEORM_ENTITIES=./dist/**/entities/*.entity.js
TYPEORM_MIGRATIONS=./dist/**/migrations/*.js
TYPEORM_ENTITIES_DIR= ./src/entities/
TYPEORM_MIGRATIONS_DIR= ./src/migrations/
TYPEORM_MIGRATIONS_RUN=false
TYPEORM_DROP_SCHEMA=false
我的环境
Dependency Version
Operating System Ubuntu 20.04
Node.js version 16.13
Typescript version 4.5.2
TypeORM version 0.3.9
找到了这个。CLI中非常丑陋的破坏性更改>=0.3.x很遗憾,但我坚信它仍然是最好的ORM。以下是我必须做的,以防止它在从0.2.x更新到0.3.11后产生大量废话。
注意:这假设您当前能够生成迁移,但当它在没有实体更改的情况下运行时,它会生成一堆毫无意义的更新。
-
完全备份本地数据库。数据/结构的完全导出。如果事情发生了问题,你会用这个来重新开始。
-
将仅数据从数据库导出到一个单独的文件中。稍后我们将使用此功能将数据库恢复到当前状态。
-
彻底清除您的本地数据库-所有表,所有数据。空数据库。
-
从您的
/migrations
文件夹中,将已在其他环境中运行的任何一个迁移复制到安全的位置。我们稍后将使用此功能将所有迁移压缩到此文件中,因为保证它已经在其他环境中运行。只需在任何/所有环境中的migrations
表中选择一个您确定存在的即可。当我们部署时,它会被跳过,并允许我们将自己重置回只有1次迁移,坦率地说,无论如何,这都需要不时进行。 -
完全清空所有迁移的
/migrations
文件夹。 -
清洁您的
/dist
文件夹-rm -rf ./dist
重要:我发现对已编译的实体运行是最安全的,所以如果您正在处理迁移,清除它很重要,因为如果不清除,任何旧的迁移都会留在dist文件夹中。
- 生成基线架构迁移。我使用的命令在package.json中是这样配置的,并使用
npm run migration:generate
调用:
"prebuild": "rm -rf ./dist",
"build": "nest build api",
"typeorm": "typeorm-ts-node-commonjs -d ormconfig.ts",
"migration:generate": "npm run build && npm run typeorm migration:generate -- ./migrations/schema"
这将输出到./migrations/1673535486257-schema.ts
(作为一个示例文件名)中,并且应该包含完整的迁移以创建整个数据库。
启动NestJs服务器(配置中有
runMigrations: true
)并让它完全启动。在这一点上,您的数据库应该是全新的,具有本地实体的完整模式,但当然除了1个迁移条目之外,它是完全空的。使用任何用于SQL导入的工具,转到并尝试导入早期的仅数据导出。这应该只在迁移表上导入一个可以忽略的错误。如果导入一切顺利,那么现在您的数据库已完全恢复到以前的状态。
重要步骤-挤压您的迁移。不要因为迁移重新开始而感到高兴而跳过这一步!你会想回去参考我们藏起来的旧迁移文件,然后做几件事:
- 更改
/migrations
文件夹中新的(也是唯一的)迁移的文件名,使其与隐藏的文件名完全匹配 - 在迁移文件本身内部,更改它生成的迁移类的字面类名,使其与旧文件中的类名完全匹配。您还需要将类名正下方的
name
属性更改为与旧文件相同。例如:
- 更改
export class schema1673535486257 implements MigrationInterface {
name = 'schema1673535486257'
public async up(queryRunner: QueryRunner): Promise<void> { ... }
public async down(queryRunner: QueryRunner): Promise<void> { ... }
}
这样做可以确保您的一次大迁移被最新的环境跳过。
现在,下次对实体进行更改并运行npm run migration:generate
时,它将是您所期望的差异迁移!
在我的一个项目中也发生了同样的事情,我仍然不知道如何从orm配置中解决它,但这种方式解决了问题。
显示错误的列定义如下
@Column({
type: 'text',
nullable: true,
name: 'action_name',
default: null
})
action_name: string;
或
@Column({
type: 'text',
nullable: true,
name: 'action_name'
})
action_name: string;
通过这种方式生成了ALTERTABLE,并且通过分析相同的查询来解析它的方式如下
@Column({
type: 'text',
nullable: true,
name: 'action_name',
default: () => 'NULL'
})
action_name: string;
如果检查down函数,您将看到它将列恢复到的窗体具有DEFAULT'NULL'。