nestjs同时支持hrm和typeorm

438 阅读1分钟
碰到一个报错信息:
EntityMetadataNotFoundError: No metadata for "User" was found
为啥会报错

image.png

github大佬的回答

Putting my two cents here for people with the same problem.

The reason this is happening is because

  1. webpack bundles all the code into a separate bundle file, and in order for HMR to work, this bundle files is loaded and run as the server
  2. specifying entities: [__dirname + '/**/*.ts'] (or .js in my case) would cause typeorm to require those files (while the real entities is already loaded in the webpack bundle).
  3. when typeorm tries to get repository, it compares the entity passed-in to getRepository (for example, getRepository(User), where this User is loaded from the webpack bundle), with the ones loaded in the entities config, which is loaded from js/ts files.
  4. Even though they have the same name, they're two different class (functions) loaded from different modules, so typeorm will not be able to find the correct one.

My workaround is based on the fact that all the modules are loaded, hence all the entities should be loaded already, via imports. This is especially true in NestJS, with the well-structured project. Specifically, for each module, either the module itself or the controller will import the entity somewhere.

By leveraging the internal mechanism of @Entity decorator, we'll be able to get a list of entity classes.

Not sure how true this is, but seems to work well with both dev and prod settings.

解决方法
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { getMetadataArgsStorage } from 'typeorm';

// The modules are loaded from here, hence importing the entities
import { AModule } from './a/a.module';
import { BModule } from './b/b.module';

@Module({
  imports: [
    AModule, 
    BModule, 
    TypeOrmModule.forRoot({ 
      ...,
      entities: getMetadataArgsStorage().tables.map(tbl => tbl.target),
      migrations: ...,
    }),
  ]
})
export class AppModule {}
github链接

github.com/nestjs/nest…

自己试了一下,重启之后需要刷新一下,才能读取到对应的entities