Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeORM: Joining when we have one to many and many to one relationship

Tags:

typeorm

nestjs

@Entity()
export class User {
  @PrimaryColumn()
  id: string;

  @Column({unique: true})
  username: string;

  @Column({unique: true})
  email: string;

  @OneToMany(type => Post, post => post.id)
  posts: Post[];
}

@Entity()
export class Post {

  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(type => User, user => user.posts)
  @JoinColumn({name: 'user_id'})
  user: User;

  @OneToMany(type => Image, image => image.id)
  images: Image[];
}
 
@Entity()
export class Image {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(type => Post, post => post.images)
  @JoinColumn({name : 'post_id'})
  post: Post;
}

I have these 3 entities and I want to make a query to have all the posts from a user and for that post to get all the images. I am trying to do this using the following code:

return await this.postRepository.createQueryBuilder("post")
  .innerJoinAndSelect("post.images", "image")
  .where("user_id = :userId", {userId: id})
  .getMany();

And I get the following error:

Cannot read property 'joinColumns' of undefined

I also tried this instead of the .innerJoin from above:

.innerJoinAndSelect(Image, "image", "image.post_id = post.id")

This way I don't get that error anymore, but as a result I get only the post and I don't get the images from it

like image 890
Darius Bogdan Avatar asked Jul 26 '18 11:07

Darius Bogdan


People also ask

How do you create a one to many relationship in TypeORM?

Here we added @OneToMany to the photos property and specified the target relation type to be Photo . You can omit @JoinColumn in a @ManyToOne / @OneToMany relation. @OneToMany cannot exist without @ManyToOne . If you want to use @OneToMany , @ManyToOne is required.

What is@ JoinColumn in TypeORM?

Join columns are always a reference to some other columns (using a foreign key). By default your relation always refers to the primary column of the related entity. If you want to create relation with other columns of the related entity - you can specify them in @JoinColumn as well: @ManyToOne(type => Category)

How do you save a many-to-many relationship in TypeORM?

Saving many-to-many relationsWith cascades enabled, you can save this relation with only one save call. question. text = "who let the dogs out?"


1 Answers

I have been struggling with the same problem myself.

You should change the relation here:

@OneToMany(type => Image, image => image.id)
images: Image[];

To this:

@OneToMany(type => Image, image => image.post)
images: Image[];

Notice that image.id should be image.post instead to match the inverse side.

*Edit => Over here the same problem appears:

@OneToMany(type => Post, post => post.id)
posts: Post[];

This relation should also have the inverse side, post.id should be post.user instead:

@OneToMany(type => Post, post => post.user)
posts: Post[];

Be careful about this since it doesn't throw any errors until runtime.

I just tested this query with the above modifications and the error is gone:

return await this.postRepository.find({
  relations: ['images', 'user'],
  where: { user: { id: id } },
});

You may also omit the @JoinColumn() decorators, as they are not necessary in one to many and many to one relationships, you can see it mentioned in the official docs:

You can omit @JoinColumn in a @ManyToOne / @OneToMany relation. @OneToMany cannot exist without @ManyToOne. If you want to use @OneToMany, @ManyToOne is required. Where you set @ManyToOne - its related entity will have "relation id" and foreign key.

Refer to the TypeORM documentation for more details about this, you will also find an example of this type of relation.

like image 114
Martin Nieves Avatar answered Sep 22 '22 07:09

Martin Nieves