EntityMetadataNotFound:没有“BusinessApplication"的元数据;被找到 [英] EntityMetadataNotFound: No metadata for "BusinessApplication" was found

查看:25
本文介绍了EntityMetadataNotFound:没有“BusinessApplication"的元数据;被找到的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用TypeORM没有问题,但是在进行API调用时突然弹出这个错误:

I've been using TypeORM with no problems for a while, but then suddenly this error pops up when making an API call:

EntityMetadataNotFound: No metadata for "BusinessApplication" was found.
    at new EntityMetadataNotFoundError (C:UsersRobbieCodefit-society
ode_modules	ypeormerrorEntityMetadataNotFoundError.js:10:28)
    at Connection.getMetadata (C:UsersRobbieCodefit-society
ode_modules	ypeormconnectionConnection.js:336:19)
    at EntityManager.<anonymous> (C:UsersRobbieCodefit-society
ode_modules	ypeormentity-managerEntityManager.js:459:44)
    at step (C:UsersRobbieCodefit-society
ode_modules	slib	slib.js:136:27)
    at Object.next (C:UsersRobbieCodefit-society
ode_modules	slib	slib.js:117:57)
    at C:UsersRobbieCodefit-society
ode_modules	slib	slib.js:110:75
    at new Promise (<anonymous>)
    at Object.__awaiter (C:UsersRobbieCodefit-society
ode_modules	slib	slib.js:106:16)
    at EntityManager.find (C:UsersRobbieCodefit-society
ode_modules	ypeormentity-managerEntityManager.js:456:24)
    at module.exports../src/pages/api/business-applications/[id].ts.__webpack_exports__.default.Object (C:UsersRobbieCodefit-society.nextserverstaticdevelopmentpagesapiusiness-applications[id].js:1648:65)
    at process._tickCallback (internal/process/next_tick.js:68:7)

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

It happens when this code is called:

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 中:

In 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';

在后端/database.ts:

In 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:

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

据我所见,导入都指向正确的文件,我导入了反射元数据,并将 @Entity() 装饰器放在 BusinessApplication班级.那么可能出了什么问题呢?值得注意的是,如果我将第一个文件中的 await manager.find(BusinessApplication, ...) 更改为 await manager.find('BusinessApplication', ...) 它可以工作很好,但我不想这样做,因为我会失去智能.此外,第一次初始化服务器时不会发生此错误,但在 Webpack 热模块重新加载后它会中断(这可能发生在 Next.js 处理页面或更改代码之后).

From what I can see, the imports all point to the right file, I imported reflect-metadata, and I put the @Entity() decorator on the BusinessApplication class. So what could be going wrong? Notably, if I change await manager.find(BusinessApplication, ...) in the first file to await manager.find('BusinessApplication', ...) it works fine, but I don't want to do that because I'll lose intellisense. Also, this error doesn't happen the first time the server is initialized, but after it is hot-module-reloaded by Webpack it breaks (this can happen after Next.js disposes of the page or after I change the code).

推荐答案

问题

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

The problem

For me, this was happening after the webpack hot-reload because when everything was reloaded, new entity models were generated. Although new entity models were generated, TypeORM didn't know about them because I only made a connection to the database once, when the database.ts module was initialized, as you can see from the file. So when TypeORM compared the new entities from the manager.find(BusinessApplication, ...) call and old entities, it said they were not the same because they don't have referential equality (no two functions are the same in JS). Therefore, it didn't find the metadata when comparing it to manager.connection.entityMetadatas, which contained the old version only.

我只需要在每次重新加载后与数据库建立新连接,以便使用新的实体元数据填充它.

I'll just need to make a new connection to the database after every reload so it is populated with the new entity metadata.

这篇关于EntityMetadataNotFound:没有“BusinessApplication"的元数据;被找到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆