实体元数据未找到:未找到“BusinessApplication”的元数据

7

我一直使用TypeORM没有问题,但是当我尝试进行API调用时,突然出现了以下错误:

EntityMetadataNotFound: No metadata for "BusinessApplication" was found.
    at new EntityMetadataNotFoundError (C:\Users\Robbie\Code\fit-society\node_modules\typeorm\error\EntityMetadataNotFoundError.js:10:28)
    at Connection.getMetadata (C:\Users\Robbie\Code\fit-society\node_modules\typeorm\connection\Connection.js:336:19)
    at EntityManager.<anonymous> (C:\Users\Robbie\Code\fit-society\node_modules\typeorm\entity-manager\EntityManager.js:459:44)
    at step (C:\Users\Robbie\Code\fit-society\node_modules\tslib\tslib.js:136:27)
    at Object.next (C:\Users\Robbie\Code\fit-society\node_modules\tslib\tslib.js:117:57)
    at C:\Users\Robbie\Code\fit-society\node_modules\tslib\tslib.js:110:75
    at new Promise (<anonymous>)
    at Object.__awaiter (C:\Users\Robbie\Code\fit-society\node_modules\tslib\tslib.js:106:16)
    at EntityManager.find (C:\Users\Robbie\Code\fit-society\node_modules\typeorm\entity-manager\EntityManager.js:456:24)
    at module.exports../src/pages/api/business-applications/[id].ts.__webpack_exports__.default.Object (C:\Users\Robbie\Code\fit-society\.next\server\static\development\pages\api\business-applications\[id].js:1648:65)
    at process._tickCallback (internal/process/next_tick.js:68:7)

当调用此代码时会发生这种情况:

import { BusinessApplication } from '../../../backend/all-entities';
import db from '../../../backend/database';

// in a function...
      const manager = await db.getManager();
      // in this case, req.data.id does equal "oldest"
      const application: BusinessApplication | undefined =
      req.data.id === 'oldest'
          ? (await manager.find(BusinessApplication, { order: { dateSubmitted: 'DESC' }, take: 1 }))[0]
          : await manager.findOne(BusinessApplication, { where: { id: parseInt(req.data.id, 10) } });
      if (application == null) throw createError(404, 'Business application not found');
      return application;

在 backend/all-entities.ts 文件中:
/**
 * This file exists to solve circular dependency problems with Webpack by explicitly specifying the module loading order.
 * @see https://medium.com/visual-development/how-to-fix-nasty-circular-dependency-issues-once-and-for-all-in-javascript-typescript-a04c987cf0de
 */

import Account_ from './entities/Account';

export { default as Qualification } from './entities/Qualification';

export { default as EditableAccount } from './entities/EditableAccount';
export { default as EditableBusiness } from './entities/EditableBusiness';
export { default as Business } from './entities/Business';
export { default as BusinessApplication, SendableBusinessApplication } from './entities/BusinessApplication';
export { default as EditableCustomer } from './entities/EditableCustomer';
export { default as Customer } from './entities/Customer';

export { default as Offer } from './entities/Offer';
export { default as ProductOffer } from './entities/ProductOffer';
export { default as ServiceOffer } from './entities/ServiceOffer';

在backend/database.ts文件中:

import 'reflect-metadata';
import {
  Connection,
  ConnectionManager,
  ConnectionOptions,
  createConnection,
  EntityManager,
  getConnectionManager
} from 'typeorm';
import { Business, BusinessApplication, Customer, ProductOffer, ServiceOffer, Qualification } from './all-entities';

/**
 * Database manager class
 */
class Database {
  private connectionManager: ConnectionManager;

  constructor() {
    this.connectionManager = getConnectionManager();
  }

  private async getConnection(): Promise<Connection> {
    const CONNECTION_NAME = 'default';
    let connection: Connection;

    if (this.connectionManager.has(CONNECTION_NAME)) {
      connection = this.connectionManager.get(CONNECTION_NAME);
      if (!connection.isConnected) {
        connection = await connection.connect();
      }
    } else {
      const connectionOptions: ConnectionOptions = {
        name: CONNECTION_NAME,
        type: 'postgres',
        url: process.env.DATABASE_URL,
        synchronize: true,
        entities: [Business, BusinessApplication, Qualification, Customer, ProductOffer, ServiceOffer]
      };
      connection = await createConnection(connectionOptions);
    }

    return connection;
  }

  public getManager(): Promise<EntityManager> {
    return this.getConnection().then(conn => conn.manager);
  }
}

const db = new Database();
export default db;

在后端/entities/BusinessApplication.ts文件中:
import { IsIn, IsString, IsOptional } from 'class-validator';
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm';
import { EditableBusiness } from '../all-entities';

class PasswordlessBusinessApplication extends EditableBusiness {
  @Column()
  @IsIn(['individual', 'company'])
  type!: 'individual' | 'company';

  @Column({ nullable: true })
  @IsOptional()
  @IsString()
  fein?: string;

  @Column({ nullable: true })
  @IsOptional()
  @IsString()
  professionalCertificationUrl?: string;
}

@Entity()
export default class BusinessApplication extends PasswordlessBusinessApplication {
  @PrimaryGeneratedColumn()
  id!: number;

  @CreateDateColumn()
  dateSubmitted!: Date;

  @Column()
  @IsString()
  passwordHash!: string;
}

/**
 * A business application sent by the client, which contains a password instead of a password hash.
 * Qualification objects do not require id or business.
 */
export class SendableBusinessApplication extends PasswordlessBusinessApplication {
  @IsString()
  password!: string;
}

从我所看到的情况来看,所有的导入都指向正确的文件,我导入了reflect-metadata,并在BusinessApplication类上放置了@Entity()修饰符。那么出了什么问题呢?值得注意的是,如果我将第一个文件中的await manager.find(BusinessApplication,...)更改为await manager.find('BusinessApplication',...),它就可以正常工作,但我不想这样做,因为我会失去智能提示。此外,在服务器初始化后的第一次操作时,不会发生此错误,但在Webpack进行热模块重新加载后会出现问题(这可能是在Next.js销毁页面或我更改代码后发生的)。
5个回答

8

问题

对于我来说,这是在webpack热重载之后发生的,因为当所有内容重新加载时,新的实体模型被生成了。尽管生成了新的实体模型,但TypeORM并不知道它们的存在,因为我仅在初始化database.ts模块时进行了一次数据库连接,正如你从文件中看到的那样。因此,当TypeORM比较manager.find(BusinessApplication, ...)调用的新实体和旧实体时,它会认为它们不同,因为它们没有引用相等性(JS中不存在两个函数是相同的)。因此,在与manager.connection.entityMetadatas比较它时,它找不到元数据,该元数据仅包含旧版本。

解决方法

我只需要在每次重新加载后对数据库进行新的连接,以便填充新的实体元数据即可。


3
你能分享一下解决方案的代码片段吗?或者提供更多关于解决方案的细节信息吗? - Akshay Pethani
@AkshayPethani 你具体想知道什么?我所做的就是创建新的连接,使用不同的名称(在我的情况下是随机生成的),而不是“默认”,然后手动关闭它们。 - Robert Moore

2

将您的项目中的dist文件夹删除,然后再次运行。


2
在没有将文件名中包含.entity的情况下重命名实体时,会收到此错误。

1

0

在花费更多时间后,我终于从我的项目中删除了dist文件夹并运行它。

它起作用了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接