TypeORM 存在依赖的ViewEntity同步创建顺序异常问题问询
TypeORM 依赖视图创建顺序混乱问题解决方案
问题根因
你尝试的所有方案都无效的核心原因是:0.3.17版本之前的TypeORM,内部处理ViewEntity时会将所有实体存入无序的对象结构中,遍历创建视图的顺序完全随机,和文件名、类名、entities数组顺序、文件创建/修改时间均无关联,所以会随机出现依赖视图先创建的报错。
QueryFailedError: relation "public.course_item_view" does not exist
可落地解决方案
方案1:使用Migration手动管理视图(推荐,生产环境适用)
生产环境本身不建议开启synchronize自动同步,用迁移手动控制顺序是最稳定的方案:
- 将连接配置中的
synchronize设置为false - 执行命令创建空迁移文件:
typeorm-ts-node-commonjs migration:create src/migrations/1690000000000-CreateRelatedViews
- 在迁移文件的
up方法中按依赖从低到高的顺序写创建视图逻辑,down方法按反向顺序写删除逻辑:
import { MigrationInterface, QueryRunner } from "typeorm"; export class CreateRelatedViews1690000000000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { // 先创建无依赖的基础视图 await queryRunner.query(`CREATE VIEW video_completed_view AS /* 对应VideoCompletedView的expression逻辑 */`); await queryRunner.query(`CREATE VIEW user_exam_completed_view AS /* 对应UserExamCompletedView的expression逻辑 */`); // 再创建依赖基础视图的视图 await queryRunner.query(`CREATE VIEW course_item_view AS /* 对应CourseItemView的expression逻辑 */`); // 最后创建依赖上层视图的最终视图 await queryRunner.query(`CREATE VIEW course_item_state_view AS /* 对应CourseItemStateView的expression逻辑 */`); } public async down(queryRunner: QueryRunner): Promise<void> { // 删除顺序和创建顺序相反 await queryRunner.query(`DROP VIEW course_item_state_view`); await queryRunner.query(`DROP VIEW course_item_view`); await queryRunner.query(`DROP VIEW user_exam_completed_view`); await queryRunner.query(`DROP VIEW video_completed_view`); } }
- 执行迁移命令即可:
typeorm-ts-node-commonjs migration:run -d src/data-source.ts
方案2:手动控制视图创建(适用开发环境快速同步)
如果开发阶段想要保留自动同步的便捷性,可以先关闭ViewEntity的自动同步,连接初始化完成后手动按顺序创建视图:
- 给所有ViewEntity添加
synchronize: false配置:
@ViewEntity({ synchronize: false, expression: `/* 原有视图逻辑 */` })
- 连接初始化完成后,按依赖顺序批量创建视图:
const connection = await createConnection(postgresOptions); // 按依赖从低到高排列视图实体 const viewCreateOrder = [ VideoCompletedView, UserExamCompletedView, UserExamAnswerSessionView, UserVideoMaxWatchedSecondsView, CourseItemView, CourseItemStateView ]; for (const ViewEntity of viewCreateOrder) { const meta = connection.getMetadata(ViewEntity); await connection.query(`CREATE OR REPLACE VIEW ${meta.tablePath} AS ${meta.expression as string}`); }
方案3:升级TypeORM版本
0.3.17及以上版本的TypeORM已经修复了视图创建顺序的问题,会优先按entities数组的顺序创建ViewEntity,升级后可直接复用你原有调整好顺序的entities配置。
内容的提问来源于stack exchange,提问作者spenglermanfred
相关产品推荐
相关产品推荐

