Search code examples
typescriptentitynestjstypeormmany-to-one

NestJS - TypeORM - ManyToOne Entity is undefined


I am trying to link to entities Child & Client

So I have created 2 entities :

// src/children/child.entity.ts

@Entity()
export class Child extends BaseEntity {

  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstname: string;

  @Column()
  lastname: string;

  @ManyToOne(type => Client, client => client.children, { eager: false })
  client: Client

  @Column()
  clientId: number;
}

and

// src/clients/client.entity.ts

@Entity()
export class Client extends BaseEntity {

  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstname: string;

  @Column()
  lastname: string;

  @OneToMany(type => Child, child => child.client, { eager: true })
  children: Child[];

}

I'm able to create a client & a child. When I get a client, I can retrieve all his children.

But I am not able to retrieve a client with a child :

For example, in children.controller.ts

enter image description here

When I visit http://locahost:3000/children/1/parent

I got on the console :

enter image description here

I am really stuck because I don't know how to solve this issue.

Here is children.module.ts

import { Module } from '@nestjs/common';
import { ChildrenController } from './children.controller';
import { ChildrenService } from './children.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ChildRepository } from './child.repository';
import { ClientRepository } from 'src/clients/client.repository';
import { ClientsService } from 'src/clients/clients.service';
import { Client } from 'src/clients/client.entity';

@Module({
  imports: [
    TypeOrmModule.forFeature([ChildRepository, ClientRepository, Client]),
  ],
  controllers: [ChildrenController],
  providers: [ChildrenService, ClientsService]
})
export class ChildrenModule {}

Here is typeorm.config

import { TypeOrmModuleOptions } from '@nestjs/typeorm';

export const typeOrmConfig: TypeOrmModuleOptions = {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'myusername',
  password: '',
  database: 'mydatabase',
  entities: [__dirname + '/../**/*.entity.{js,ts}'],
  synchronize: true,
}

Edit 1 :

children.controller.ts

// src/children/children.controller.ts

@Controller('children')
export class ChildrenController {

  constructor(
    private childrenService: ChildrenService,
    private clientsService: ClientsService
  ) {}

  @Get('/:id')
  async getChild(id: number): Promise<Child> {
    return await this.childrenService.getChild(id);
  }
}

children.service.ts

// src/children/children.service.ts

@Injectable()
export class ChildrenService {
  constructor(
    @InjectRepository(ChildRepository)
    private childRepository: ChildRepository,
    @InjectRepository(ClientRepository)
    private clientRepository: ClientRepository
  ) {}

  async getChild(id: number): Promise<Child> {
    return await this.childRepository.findOne(id)
  }
}

Thanks for you help 😀


Solution

  • It seems to me that you forgot add @JoinColumn() on ManyToOne side of this relation. Try enhance your code in this way

    
    @Entity()
    export class Child extends BaseEntity {
    
      @PrimaryGeneratedColumn()
      id: number;
    
      @Column()
      firstname: string;
    
      @Column()
      lastname: string;
    
      @ManyToOne(type => Client, client => client.children, { eager: false })
      @JoinColumn()
      client: Client
    
      @Column()
      clientId: number;
    }
    

    Also, pay attention on eager parameter. If it set as true this relation will be loaded automatically even you didn't require it manually, otherwise you have to specify that you want relation to be loaded. Try enhance children.service.ts like this:

      async getChild(id: number): Promise<Child> {
        return await this.childRepository.findOne(id, {
          relations: ['client']
        })
      }
    

    or you can set this relation as eager and it will be loaded automatically every time when you load Child

      @ManyToOne(type => Client, client => client.children, { eager: true })
      @JoinColumn()
      client: Client