简体   繁体   中英

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

I am having a fun issue trying to get TypeOrm to work in my nestjs project.

I have the below code to configure my project, yes everything loads, and yes I am able to connect to my database.

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) {}
}

and here are the entities:

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

I originally tried doing a glob pattern match, to no avail, so now I am directly importing in my Entities until I can get something to run. Also note, that all my modules load prior to the error above and the error is from using the @InjectRepository() decorator within either the AuthenticationController or AdminController. Everywhere I have looked has said its because my entities are not being loaded, which I am not sure how that is possible. Thanks.

In my case I had an error on Production mode, to fix it I added the path of the compiled JS files in the build folder.

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,
  },
};

The short version could be: entities: ['**/src/entity/*{.ts,.js}'],

Try giving a name to your entity with the @Entity decorator:

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

seems like it is, as you said, because the entities are not loaded.

my guess is: the config file you have added tries to find the files at:

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

are those entity files in the same dir as the module is? could help to print the output of those paths just to make sure it is correct.

also note that typescript compiles to javascript, so you might run into the same problem if you run the code from /dist, because it will be able to see only the ".js" compiled files, so i'd suggest to use

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

if its nothing of the above 2 options, please provide the full routes of the entities and modules in play.

I faced the same issue, glob paths don't work in case of monorepo .

Note, however, that glob paths are not supported by webpack , so if you are building your application within a monorepo , you won't be able to use them. To address this issue, an alternative solution is provided. To automatically load entities, set the autoLoadEntities property of the configuration object (passed into the forRoot() method).

Note that entities that aren't registered through the forFeature() method, but are only referenced from the entity (via a relationship), won't be included by way of the autoLoadEntities setting.

-- NestJS Docs

Also, I was using ormconfig.ts , which also presents one more difficulty -

Note that the ormconfig.json file is loaded by the typeorm library. Thus, any of the extra properties described above (which are supported internally by way of the forRoot() method - for example, autoLoadEntities and retryDelay) won't be applied. Luckily, TypeORM provides the getConnectionOptions function that reads connection options from the ormconfig file or environment variables. With this, you can still use the configuration file and set Nest-specific options.

-- NestJS Docs

Final Solution

  1. root/main module -
import { getConnectionOptions } from 'typeorm';
...
@Module({
  imports: [
   TypeOrmModule.forRootAsync({
    useFactory: async () =>
      Object.assign(await 
       getConnectionOptions(), {
        autoLoadEntities: true,
      }),
    })
   ],
 ...
})
  1. app/child module -
...
@Module({
  imports: [TypeOrmModule.forFeature([<entities go here>])],
  ...
})
...

In my case, I solved it by declaring the entity in the connection file.

The TypeORM documentation explains this change.

Creating a connection to the database

Now, when our entity is created, let's create an index.ts (or app.ts whatever you call it) file and set up our connection there:

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

Make sure you put the @ sign in front of your entity decorator (3 of my entities didn't and the error message was related to the relations because it didn't find my entites)

I had the same problem and I added the following properties in my ormconfig:

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

Works fine to me.

When reading the source code I realized that the strings are still there (inside the JS bundle), so it is calling something that is just not there as all files are inside of it, I tried importing the models directly within the app.module and not passing strings or patterns to the entities array, but the imported entity classes instead, that worked like a charm.

Given, this may not be the cleanest approach, because you have to write the paths in the imports to different modules and import them one by one. It would be great to see what others have to say on how to tackle and improve on this so that we can achieve a cleaner solution.

This works today as of Nov/2021.

Make sure you annotated the entity class with @Entity()

Example

@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;
}

Also check your connection, if entities are entities: ['dist/**/*.entity.js'] , make sure your file name is {name}.entity.ts

in base entity you havent provided decorator @Entity()

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

}

In my case it was because I had the repository inside the list of:

TypeOrmModule.forFeature([ 
    TblX,
    RepositoryX
]),

Removing RepositoryX from here fixed it.

I had everything correct except the filename.

It should be like entityname.entity.ts

But it was like entityname.ts

you can have this error also in case you register the services in the import statment like this

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

this will throw the same error

If all of the answers above do not work, you could simply just clear and rebuild the dist directory by running the following command

npm run build

Then, restart your application

npm run start:dev

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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