many-to-one-one-to-many-relations
Many-to-one / one-to-many是一种关系,其中A包含多个B的实例,但B只包含一个A的实例。
让我们以User
和Photo
实体为例。
用户可以拥有多张照片,但每张照片只属于一个用户。
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
来加载关系。