typescript - EntityMetadataNotFound: "BusinessApplication" için metadata bulunamadı
Bir süredir TypeORM'u sorunsuz bir şekilde kullanıyordum, ama sonra bir API çağrısı yaparken aniden bu hata ortaya çıkıyor:
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)
Bu kod çağrıldığında olur:
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 içinde:
/**
* 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 dosyasında:
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/entities/BusinessApplication.ts içinde:
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;
}
Gördüğüm kadarıyla, tüm importlar doğru dosyayı işaret ediyor, reflect-metadata'i import ettim ve BusinessApplication sınıfına @Entity() dekoratörünü koydum. Peki yanlış giden ne olabilir? Özellikle, eğer ilk dosyada await manager.find(BusinessApplication, ...) ifadesini await manager.find('BusinessApplication', ...) olarak değiştirirsem her şey düzgün çalışıyor, ama bunu yapmak istemiyorum çünkü intellisense'i kaybedeceğim. Ayrıca, bu hata sunucu ilk kez başlatıldığında meydana gelmiyor, ancak Webpack tarafından hot-module-reload yapıldığında kırılıyor (bu, Next.js sayfayı dispose ettikten sonra veya kodu değiştirdikten sonra olabilir).
Cevap #1
Sorun
Benim için bu, webpack sıcak-yeniden yüklemesinden sonra oluyordu çünkü her şey yeniden yüklendiğinde yeni varlık modelleri oluşturuluyordu. Yeni varlık modelleri oluşturulmuş olmasına rağmen, TypeORM bunlardan haberdar değildi çünkü sadece database.ts modülü başlatıldığında bir kez veritabanına bağlandım, dosyadan görebileceğiniz gibi. Bu yüzden TypeORM manager.find(BusinessApplication, ...) çağrısından gelen yeni varlıkları eski varlıklarla karşılaştırdığında, referans eşitliği olmadığı için aynı olmadıklarını söyledi (JS'te iki fonksiyon aynı değildir). Bu nedenle, sadece eski sürümü içeren manager.connection.entityMetadatas ile karşılaştırırken meta veriyi bulamadı.
Düzeltme
Her yeniden yüklemeden sonra veritabanına yeni bir bağlantı yapmam gerekecek, böylece yeni varlık meta verileri ile doldurulmuş olacak.
Cevap #2
projenizden dist klasörünü kaldırın ve tekrar çalıştırın