一对一关系
一对一关系是A包含一个B实例,而B仅包含一个A实例的关系。
我们以User
和Profile
实体为例。
用户只能有一个个人资料,而个人资料只属于一个用户。
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number
@Column()
gender: string
@Column()
photo: string
}
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToOne(() => Profile)
@JoinColumn()
profile: Profile
}
在user
上添加了@OneToOne
,并指定目标关系类型为Profile
。
我们还添加了@JoinColumn
,它是必需的,并且只能在关系的一侧设置。
您在@JoinColumn
所在的一侧的表将包含一个"relation id"和指向目标实体表的外键。
此示例将产生以下表格:
+-------------+--------------+----------------------------+
| profile |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| gender | varchar(255) | |
| photo | varchar(255) | |
+-------------+--------------+----------------------------+
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
| profileId | int(11) | FOREIGN KEY |
+-------------+--------------+----------------------------+
同样,@JoinColumn
必须仅在关系的一侧设置 - 必须在数据库表中具有外键的一侧。
保存这样的关系的示例:
const profile = new Profile()
profile.gender = "male"
profile.photo = "me.jpg"
await dataSource.manager.save(profile)
const user = new User()
user.name = "Joe Smith"
user.profile = profile
await dataSource.manager.save(user)
使用cascades启用后,您可以通过仅调用一次save
来保存此关系。
要在加载用户的同时加载个人资料,您必须在FindOptions
中指定关系:
const users = await dataSource.getRepository(User).find({
relations: {
profile: true,
},
})
或者使用QueryBuilder
将它们连接起来:
const users = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile")
.getMany()
使用启用了eager loading的关系,您不必在find命令中指定关系,因为它将自动始终自动加载。如果使用 QueryBuilder,则禁用了eager relations,您必须使用leftJoinAndSelect
来加载关系。
关系可以是单向的或双向的。 单向关系是指只在一个方向上使用关系装饰器的关系。 双向关系是指在关系的两个方向上都使用关系装饰器。
我们刚刚创建了一个单向关系。让我们将其改为双向关系:
import { Entity, PrimaryGeneratedColumn, Column, OneToOne } from "typeorm"
import { User } from "./User"
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number
@Column()
gender: string
@Column()
photo: string
@OneToOne(() => User, (user) => user.profile) // 在第二个参数中指定反向关系
user: User
}
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToOne(() => Profile, (profile) => profile.user) // 在第二个参数中指定反向关系
@JoinColumn()
profile: Profile
}
我们刚刚创建了一个双向关系。请注意,反向关系没有@JoinColumn
。
@JoinColumn
仅必须在关系的一侧上设置 - 在拥有外键的表中。
双向关系允许您使用QueryBuilder
从两个方向连接关系:
const profiles = await dataSource
.getRepository(Profile)
.createQueryBuilder("profile")
.leftJoinAndSelect("profile.user", "user")
.getMany()