簡體   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