EntityMetadataNotFound: Метаданные для «BusinessApplication» не найдены - PullRequest
1 голос
/ 14 марта 2020

Я уже некоторое время использую 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-entity.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;

В backend / entity / 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;
}

Из того, что я вижу, все импортируемые точки указывают на нужный файл, я импортировал метаданные отражений и поместил декоратор @Entity() в класс BusinessApplication. Так что может пойти не так? Примечательно, что если я изменю await manager.find(BusinessApplication, ...) в первом файле на await manager.find('BusinessApplication', ...), он будет работать нормально, но я не хочу этого делать, потому что потеряю intellisense. Кроме того, эта ошибка не возникает при первой инициализации сервера, но после его горячей перезагрузки модулем Webpack происходит сбой (это может произойти после того, как Next. js удалит страницу или после того, как я изменю код) .

1 Ответ

1 голос
/ 14 марта 2020

Проблема

Для меня это происходило после горячей перезагрузки веб-пакета, потому что, когда все было перезагружено, генерировались новые модели сущностей. Хотя были созданы новые модели сущностей, TypeORM не знал о них, потому что я только один раз установил соединение с базой данных, когда был инициализирован модуль database.ts, как вы можете видеть из файла. Поэтому, когда TypeORM сравнивал новые сущности из вызова manager.find(BusinessApplication, ...) и старые сущности, он говорил, что они не были одинаковыми, потому что у них нет ссылочного равенства (никакие две функции не совпадают в JS). Поэтому он не нашел метаданные при сравнении с manager.connection.entityMetadatas, который содержал только старую версию.

Исправление

Мне просто нужно установить новое соединение с база данных после каждой перезагрузки, поэтому она заполняется новыми метаданными сущности.

...