繁体   English   中英

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

[英]RepositoryNotFoundError: No repository for "User" was found. Looks like this entity is not registered in current "default" connection? Typeorm

我在尝试让 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) {}
}

以下是实体:

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();
  }
}
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;
}

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

在我的情况下,我在生产模式下遇到错误,为了修复它,我在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,
  },
};

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

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

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

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

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

  migrations: [__dirname + '/migrations/**/*.ts'],
  subscribers: [__dirname + '/subscribers/**/*.ts'],

这些实体文件是否与模块位于同一目录中? 可以帮助打印这些路径的 output 以确保它是正确的。

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

  migrations: [__dirname + '/migrations/**/*{.ts,.js}'],
  subscribers: [__dirname + '/subscribers/**/*{.ts,.js}'],

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

我遇到了同样的问题,在monorepo的情况下,全局路径不起作用。

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

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

-- NestJS 文档

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

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

-- NestJS 文档

最终解决方案

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

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

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));

确保将 @ 符号放在实体装饰器前面(我的 3 个实体没有,并且错误消息与关系有关,因为它没有找到我的实体)

我有同样的问题,我在我的 ormconfig 中添加了以下属性:

 "cli":{ "migrationsDir":"./src/database/migrations", "entitiesDir": ".src/modules/cars/entities" }, "entities": [ "./src/modules/cars/entities/**/*{.ts,.js}" ]

对我来说很好。

阅读源代码时,我意识到字符串仍然存在(在 JS 包中),所以它调用了一些不存在的东西,因为所有文件都在其中,我尝试直接在 app.module 中导入模型和不是将字符串或模式传递给实体数组,而是导入的实体类,这就像一个魅力。

鉴于此,这可能不是最干净的方法,因为您必须将导入中的路径写入不同的模块并一一导入。 很高兴看到其他人对如何解决和改进这个问题有什么看法,以便我们能够实现更清洁的解决方案。

这适用于今天 2021 年 11 月。

确保您使用 @Entity() 注释了实体 class

例子

@Entity() <-- IMPORTANT
export class Tax {
  @PrimaryGeneratedColumn()
  taxId: number;

  @Column({ type: 'varchar', length: 48 })
  name: string;

  @Column({ type: 'varchar', length: 128 })
  description: string;

  @Column({ type: 'smallint' })
  rate: string;
}

还要检查您的连接,如果实体是entities: ['dist/**/*.entity.js'] ,请确保您的文件名是{name}.entity.ts

在基本实体中,您没有提供装饰器 @Entity()

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

}

就我而言,这是因为我的存储库位于以下列表中:

TypeOrmModule.forFeature([ 
    TblX,
    RepositoryX
]),

从这里删除 RepositoryX 修复了它。

除了文件名,我一切都正确。

它应该像entityname.entity.ts

但它就像entityname.ts

如果您像这样在导入语句中注册服务,也会出现此错误

``` imports: [
        TypeOrmModule.forFeature([
          LevelService
        ])
      ],```

这将引发相同的错误

如果以上所有答案都不起作用,您只需通过运行以下命令清除并重建dist目录

npm run build

然后,重新启动您的应用程序

npm run start:dev

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM