RepositoryNotFoundError:找不到“用户”的存储库。看起来这个实体没有在当前的“默认”连接中注册?打字机

the*_*ing 7 postgresql node.js typeorm nestjs

我在尝试让 TypeOrm 在我的 nestjs 项目中工作时遇到了一个有趣的问题。

我有以下代码来配置我的项目,是的,一切都加载了,是的,我能够连接到我的数据库。

import { CacheModule, Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { ConfigModule } from '@nestjs/config';
import { AuthenticationController } from './controllers/authentication.controller';
import { AuthenticationService } from './services/authentication.service';
import { Connection } from 'typeorm';
import { BaseEntity } from './entities/base.entity';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRoot({
        type: 'postgres',
        host: 'localhost',
        port: 5432,
        username: 'postgres',
        password: process.env.POSTGRE_PASSWORD,
        database: process.env.DATABASE,
        migrationsTableName: 'migration_table',
        entities: [User, BaseEntity],
        migrations: [__dirname + '/migrations/**/*.ts'],
        subscribers: [__dirname + '/subscribers/**/*.ts'],
        cli: {
          entitiesDir: '/entitys',
          migrationsDir: '/migrations',
          subscribersDir: '/subscribers',
        },
        synchronize: true,
        autoLoadEntities: true,
    }),
    CacheModule.register(),
    PassportModule,
    JwtModule.register({
      secret: 'myprivatekey',
      signOptions: { expiresIn: '1d' },
    }),
  ],
  controllers: [AuthenticationController],
  providers: [AuthenticationService],
})
export class AppModule {
  constructor(private connection: Connection) {}
}
Run Code Online (Sandbox Code Playgroud)

以下是实体:

import {
  Column,
  BeforeUpdate,
  BeforeInsert,
} from 'typeorm';

export class BaseEntity {
  @Column()
  created_at: Date;

  @Column({
    default: new Date(),
  })
  updated_at: Date;

  @BeforeUpdate()
  updateUpdatedAt() {
    this.updated_at = new Date();
  }

  @BeforeInsert()
  updateCreatedAt() {
    this.created_at = new Date();
  }
}
Run Code Online (Sandbox Code Playgroud)
import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  Generated,
} from 'typeorm';

import { BaseEntity } from './base.entity';

@Entity('users')
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  @Generated('uuid')
  uuid: string;

  @Column()
  first_name: string;

  @Column()
  last_name: string;

  @Column()
  email: string;

  @Column()
  password: string;

  @Column({
    default: false,
  })
  confirmed: boolean;

  @Column({
    default: null,
  })
  seller_id: string;

  @Column({
    default: null,
  })
  auth_token: string;

  @Column({
    default: false,
  })
  is_admin: boolean;
}
Run Code Online (Sandbox Code Playgroud)

我最初尝试进行 glob 模式匹配,但无济于事,所以现在我直接导入我的实体,直到我可以运行一些东西。另请注意,我的所有模块都在上述错误之前加载,错误来自在 AuthenticationController 或 AdminController 中使用 @InjectRepository() 装饰器。我看过的所有地方都说它是因为我的实体没有被加载,我不确定这怎么可能。谢谢。

小智 17

尝试使用 @Entity 装饰器为您的实体命名:

import { Entity, PrimaryColumn, Column } from "typeorm";
@Entity("category") // <-- Right here
Run Code Online (Sandbox Code Playgroud)

  • 是的..这有效。 (2认同)

ada*_*amC 8

正如您所说,似乎是这样,因为实体未加载。

我的猜测是:您添加的配置文件尝试在以下位置查找文件:

  migrations: [__dirname + '/migrations/**/*.ts'],
  subscribers: [__dirname + '/subscribers/**/*.ts'],
Run Code Online (Sandbox Code Playgroud)

这些实体文件与模块位于同一目录中吗?可以帮助打印这些路径的输出以确保其正确。

另请注意,typescript 编译为 javascript,因此如果从 /dist 运行代码,您可能会遇到同样的问题,因为它将只能看到“.js”编译文件,所以我建议使用

  migrations: [__dirname + '/migrations/**/*{.ts,.js}'],
  subscribers: [__dirname + '/subscribers/**/*{.ts,.js}'],
Run Code Online (Sandbox Code Playgroud)

如果以上两个选项都不是,请提供正在运行的实体和模块的完整路线。


Duk*_*e79 8

我遇到了同样的问题,全局路径在monorepo.

但请注意,webpack 不支持 glob 路径,因此如果您在monorepo中构建应用程序,则将无法使用它们。为了解决这个问题,提供了替代解决方案。要自动加载实体,请设置配置对象的 autoLoadEntities 属性(传递到 forRoot() 方法中)。

请注意,未通过 forFeature() 方法注册但仅从实体引用(通过关系)的实体将不会通过 autoLoadEntities 设置包含在内。

-- NestJS 文档

另外,我正在使用ormconfig.ts,这也带来了另一个困难 -

请注意,ormconfig.json 文件是由 typeorm 库加载的。因此,上述任何额外属性(通过 forRoot() 方法在内部支持 - 例如,autoLoadEntities 和 retryDelay)都不会应用。幸运的是,TypeORM 提供了 getConnectionOptions 函数,可以从 ormconfig 文件或环境变量中读取连接选项。这样,您仍然可以使用配置文件并设置 Nest 特定的选项。

-- NestJS 文档

最终解决方案

  1. 根/主模块 -
import { getConnectionOptions } from 'typeorm';
...
@Module({
  imports: [
   TypeOrmModule.forRootAsync({
    useFactory: async () =>
      Object.assign(await 
       getConnectionOptions(), {
        autoLoadEntities: true,
      }),
    })
   ],
 ...
})
Run Code Online (Sandbox Code Playgroud)
  1. 应用程序/子模块 -
...
@Module({
  imports: [TypeOrmModule.forFeature([<entities go here>])],
  ...
})
...
Run Code Online (Sandbox Code Playgroud)

  • 谢谢这对我有用。我也在使用 monorepo。 (2认同)

小智 6

在我的情况下,我在生产模式下出错,为了修复它,我在build文件夹中添加了已编译的 JS 文件的路径。

const conn: MongoConnectionOptions = {
  type: 'mongodb',
  url: DB_URL,
  synchronize: true,
  useNewUrlParser: true,
  useUnifiedTopology: true,
  logging: true,
  entities: ['src/entity/*.ts', './build/src/entity/*.js'], // <- Here!
  migrations: ['src/migration/**/*.ts'],
  subscribers: ['src/subscriber/**/*.ts'],
  cli: {
    entitiesDir: 'src/entity',
    migrationsDir: 'src/migration',
    subscribersDir: 'src/subscriber',
  },
  extra: {
    authSource: DB_AUTH_SOURCE,
  },
};
Run Code Online (Sandbox Code Playgroud)

简短版本可能是: entities: ['**/src/entity/*{.ts,.js}'],


lee*_*eam 5

就我而言,我通过在连接文件中声明实体来解决它。

TypeORM 文档解释了这一变化。

创建与数据库的连接

现在,创建我们的实体后,让我们创建一个 index.ts (或 app.ts 无论你怎么称呼它)文件并在那里设置我们的连接:

import "reflect-metadata";
import { createConnection } from "typeorm";
import { Photo } from "./entity/Photo";

createConnection({
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "root",
    password: "admin",
    database: "test",
    entities: [
        Photo
    ],
    synchronize: true,
    logging: false
}).then(connection => {
    // here you can start to work with your entities
}).catch(error => console.log(error));
Run Code Online (Sandbox Code Playgroud)