无法通过类型形式迁移删除列



我有一个测试实体,具有creatorId字段,最初为integer类型,在将其更改为string并运行迁移后,它仍然是int类型,因此我完全删除了该字段并添加了另一个字段userId并运行迁移,这次它添加了userId列,但没有删除creatorId列。

测试实体:

@ObjectType()
@Entity()
export class Test extends BaseEntity {
@Field()
@PrimaryGeneratedColumn()
id!: number;
@Field(() => String)
@Column()
creatorId: string; // problem here
@ManyToOne(() => User, (user) => user.tests)
creator: User;
@Field()
@Column()
time: string;
@Field()
@Column()
accuracy: string;
@Field()
@Column()
wpm: number;
@Field()
@Column()
chars: string;
@Field(() => String)
@CreateDateColumn()
createdAt: Date;
}
<<p>脚本/strong>
"scripts": {
"watch": "tsc -w",
"dev": "nodemon dist/index.js",
"start": "node dist/index.js",
"typeorm": "ts-node ./node_modules/typeorm/cli",
"migration:create": "typeorm migration:create ./src/migrations/migration",
"migration:run": "ts-node ./node_modules/typeorm/cli --dataSource ./dist/data-source.js migration:run",
"migration:generate": "ts-node ./node_modules/typeorm/cli --dataSource ./dist/data-source.js migration:generate ./src/migrations/migration",
"migration:show": "ts-node ./node_modules/typeorm/cli --dataSource ./dist/data-source.js migration:show"
},

data-source.ts

import { DataSource } from 'typeorm';
import dotenv from 'dotenv';
import { User } from './entities/user';
import { Test } from './entities/test';
dotenv.config();
export const AppDataSource = new DataSource({
type: 'postgres',
host: 'localhost',
port: 5432,
database: 'type-io',
username: process.env.DATABASE_USERNAME?.toString(),
password: process.env.DATABASE_PASSWORD?.toString(),
logging: true,
synchronize: false,
entities: [Test, User],
migrations: [],
cache: false,
});
AppDataSource.initialize()
.then(async () => {
console.log('Data Source has been initialized!');
})
.catch((err) => {
console.error('Error during Data Source initialization', err);
});

还有migrations字段为空的原因,因为只有当我从迁移文件导入迁移类时,它才会工作,引用路径不起作用

下面是一个示例,当我将userId字段重命名为creatatorid时,生成的查询如下:

import { MigrationInterface, QueryRunner } from "typeorm";
export class migration1680420345316 implements MigrationInterface {
name = 'migration1680420345316'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "test" DROP COLUMN "userId"`);
await queryRunner.query(`ALTER TABLE "test" DROP CONSTRAINT "FK_ab6d476e7698322a3a35b5fdb12"`);
await queryRunner.query(`ALTER TABLE "test" ALTER COLUMN "creatorId" SET NOT NULL`);
await queryRunner.query(`ALTER TABLE "test" ADD CONSTRAINT "FK_ab6d476e7698322a3a35b5fdb12" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "test" DROP CONSTRAINT "FK_ab6d476e7698322a3a35b5fdb12"`);
await queryRunner.query(`ALTER TABLE "test" ALTER COLUMN "creatorId" DROP NOT NULL`);
await queryRunner.query(`ALTER TABLE "test" ADD CONSTRAINT "FK_ab6d476e7698322a3a35b5fdb12" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "test" ADD "userId" character varying NOT NULL`);
}
}

我认为错误与typeorm entity metadata有关,也许清除它会修复错误,但到目前为止,我不知道如何做到这一点。

经过几个小时的调试,我发现问题不在于typeorm entity metadata,而在于User entity中的哪一列与Test实体中的creatorId列被引用了。默认情况下,integer类型的id字段被引用,因此creatorIdid字段必须具有相同的类型,因此当迁移正在运行时,它创建的creatorId字段类型为int。我通过引用uid字段修复了这个问题,该字段是character varying类型,修改实体如下:

@ObjectType()
@Entity()
export class Test extends BaseEntity {
@Field()
@Column()
creatorId: string;
@ManyToOne(() => User, (user) => user.tests)
@JoinColumn({ name: 'creatorId', referencedColumnName: 'uid' })
creator: User;
}