Many-to-one / one-to-many relations

Many-to-one / one-to-many is a relation where A contains multiple instances of B, but B contains only one instance of A.Let’s take for example User and Photo entities.User can have multiple photos, but each photo is owned by only one single user.

  1. import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm";
  2. import {User} from "./User";
  3. @Entity()
  4. export class Photo {
  5. @PrimaryGeneratedColumn()
  6. id: number;
  7. @Column()
  8. url: string;
  9. @ManyToOne(type => User, user => user.photos)
  10. user: User;
  11. }
  1. import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm";
  2. import {Photo} from "./Photo";
  3. @Entity()
  4. export class User {
  5. @PrimaryGeneratedColumn()
  6. id: number;
  7. @Column()
  8. name: string;
  9. @OneToMany(type => Photo, photo => photo.user)
  10. photos: Photo[];
  11. }

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. However, the inverse is not required: If you only care about the @ManyToOne relationship, you can define it without having @OneToMany on the related entity.Where you set @ManyToOne - its related entity will have “relation id” and foreign key.

This example will produce following tables:

  1. +-------------+--------------+----------------------------+
  2. | photo |
  3. +-------------+--------------+----------------------------+
  4. | id | int(11) | PRIMARY KEY AUTO_INCREMENT |
  5. | url | varchar(255) | |
  6. | userId | int(11) | FOREIGN KEY |
  7. +-------------+--------------+----------------------------+
  8. +-------------+--------------+----------------------------+
  9. | user |
  10. +-------------+--------------+----------------------------+
  11. | id | int(11) | PRIMARY KEY AUTO_INCREMENT |
  12. | name | varchar(255) | |
  13. +-------------+--------------+----------------------------+

Example how to save such relation:

  1. const photo1 = new Photo();
  2. photo1.url = "me.jpg";
  3. await connection.manager.save(photo1);
  4. const photo2 = new Photo();
  5. photo2.url = "me-and-bears.jpg";
  6. await connection.manager.save(photo2);
  7. const user = new User();
  8. user.name = "John";
  9. user.photos = [photo1, photo2];
  10. await connection.manager.save(user);

or alternative you can do:

  1. const user = new User();
  2. user.name = "Leo";
  3. await connection.manager.save(user);
  4. const photo1 = new Photo();
  5. photo1.url = "me.jpg";
  6. photo1.user = user;
  7. await connection.manager.save(photo1);
  8. const photo2 = new Photo();
  9. photo2.url = "me-and-bears.jpg";
  10. photo2.user = user;
  11. await connection.manager.save(photo2);

With cascades enabled you can save this relation with only one save call.

To load a user with photos inside you must specify the relation in FindOptions:

  1. const userRepository = connection.getRepository(User);
  2. const users = await userRepository.find({ relations: ["photos"] });
  3. // or from inverse side
  4. const photoRepository = connection.getRepository(Photo);
  5. const photos = await photoRepository.find({ relations: ["user"] });

Or using QueryBuilder you can join them:

  1. const users = await connection
  2. .getRepository(User)
  3. .createQueryBuilder("user")
  4. .leftJoinAndSelect("user.photos", "photo")
  5. .getMany();
  6. // or from inverse side
  7. const photos = await connection
  8. .getRepository(Photo)
  9. .createQueryBuilder("photo")
  10. .leftJoinAndSelect("photo.user", "user")
  11. .getMany();

With eager loading enabled on a relation you don’t have to specify relation or join it - it will ALWAYS be loaded automatically.