跳转到主要内容

many-to-one-one-to-many-relations

Many-to-one / one-to-many是一种关系,其中A包含多个B的实例,但B只包含一个A的实例。 让我们以UserPhoto实体为例。 用户可以拥有多张照片,但每张照片只属于一个用户。

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
import { User } from "./User"

@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number

@Column()
url: string

@ManyToOne(() => User, (user) => user.photos)
user: User
}
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm"
import { Photo } from "./Photo"

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@OneToMany(() => Photo, (photo) => photo.user)
photos: Photo[]
}

我们在 photos 属性上添加了 @OneToMany,并指定目标关系类型为 Photo。 在 @ManyToOne / @OneToMany 关系中,您可以省略 @JoinColumn@OneToMany 不能单独存在,必须与 @ManyToOne 搭配使用。 如果要使用 @OneToMany,则需要 @ManyToOne。但反之不需要:如果只关心 @ManyToOne 关系,可以在相关实体中定义它,而无需在关联实体上使用 @OneToMany。 在设置 @ManyToOne 的地方 - 其关联的实体将具有 "关联 id" 和外键。

这个示例将生成以下表格:

+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| url | varchar(255) | |
| userId | int(11) | FOREIGN KEY |
+-------------+--------------+----------------------------+

+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+

保存这样的关系的示例:

const photo1 = new Photo()
photo1.url = "me.jpg"
await dataSource.manager.save(photo1)

const photo2 = new Photo()
photo2.url = "me-and-bears.jpg"
await dataSource.manager.save(photo2)

const user = new User()
user.name = "John"
user.photos = [photo1, photo2]
await dataSource.manager.save(user)

或者您也可以这样做:

const user = new User()
user.name = "Leo"
await dataSource.manager.save(user)

const photo1 = new Photo()
photo1.url = "me.jpg"
photo1.user = user
await dataSource.manager.save(photo1)

const photo2 = new Photo()
photo2.url = "me-and-bears.jpg"
photo2.user = user
await dataSource.manager.save(photo2)

使用 级联操作 启用后,您可以使用一次 save 调用保存此关系。

要加载包含照片的用户,必须在 FindOptions 中指定关系:

const userRepository = dataSource.getRepository(User)
const users = await userRepository.find({
relations: {
photos: true,
},
})

// or from inverse side

const photoRepository = dataSource.getRepository(Photo)
const photos = await photoRepository.find({
relations: {
user: true,
},
})

或者使用 QueryBuilder 进行连接:

const users = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.photos", "photo")
.getMany()

// or from inverse side

const photos = await dataSource
.getRepository(Photo)
.createQueryBuilder("photo")
.leftJoinAndSelect("photo.user", "user")
.getMany()

在启用了 eager loading 的关系上,您无需在查找命令中指定关系,因为它将始终自动加载。 如果使用 QueryBuilder,则禁用了 eager relations,您必须使用 leftJoinAndSelect 来加载关系。