用户和身份证是一对一的关系,即一个用户对应一个身份证。
一对一是通过外键来存储这种关系的。
创建数据库并初始化 TypeORM 项目
ts
# 创建数据库
create database typeorm_one_to_one_relation_mapping;
# 初始化 TypeORM 项目
npx typeorm@latest init --name typeorm_one_to_one_relation_mapping --database mysql
修改数据库连接配置
具体参数配置可查看上一篇文章: TypeORM 基础篇:项目初始化与增删改查全流程
ts
import "reflect-metadata"
import {DataSource} from "typeorm"
import {User} from "./entity/User"
export const AppDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "admin",
database: "typeorm_one_to_one_relation_mapping",
synchronize: true,
logging: true,
entities: [User],
migrations: [],
subscribers: [],
poolSize: 10,
connectorPackage: "mysql2",
extra: {
authPlugins: 'sha256_password'
}
})
安装 mysql2 驱动包
bash
npm i mysql2 --save
运行项目
bash
npm run start
可以看到建表和插入数据的 sql 执行日志。

创建身份证表
创建 IdCard Entity
ts
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
@Entity({
name: "id_card"
})
export class IdCard {
@PrimaryGeneratedColumn()
id: number;
@Column({
length: 50,
comment: "身份证号"
})
cardNumber: string;
}
在 DataSource 的 entities 中引入
ts
import "reflect-metadata"
import {DataSource} from "typeorm"
import {User} from "./entity/User"
import {IdCard} from "./entity/IdCard";
export const AppDataSource = new DataSource({
// ...
entities: [User, IdCard],
// ...
})
重新执行 npm run start 可以看到建表 sql

user 表和 IdCard 表建立一对一关联
IdCard 表中维护外键
在 IdCard Entity 中添加 user 列
@OneToOne()
指定它和 User 是一对一的关系- @JoinColum() 指定外键列在 IdCard 表中维护

重新执行 npm run start 可以看到日志:

设置外键级联关系

通过主表中如何访问到从表
如何在 user 表中访问 idCard 表?同样通过 @OneToOne 装饰器。
通过第二个参数告诉 typeorm,外键是另一个 Entity 的哪个属性。

查询主表带出从表数据
ts
const users = await AppDataSource.manager.find(User, {
relations: {
idCard: true
}
})
console.log(users)
查询结果:

增删改查
新增
ts
import {AppDataSource} from "./data-source"
import {User} from "./entity/User"
import {IdCard} from "./entity/IdCard";
AppDataSource.initialize().then(async () => {
const user = new User()
user.firstName = "San"
user.lastName = "Shi"
user.age = 30
await AppDataSource.manager.save(user)
const idCard = new IdCard()
idCard.cardNumber = "1234567890"
idCard.user = user
await AppDataSource.manager.save(user)
await AppDataSource.manager.save(idCard)
}).catch(error => console.log(error))
- 创建 user 和 idCard 对象
- 设置 idCard.user 为 user,也就是建立关联关系
分别保存 user 和 idCard。
再次执行 npm run start。

查询数据库中可以看到输入插入成功

优化
上边先保存了 user 又保存了 idCard,能不能让它自动按照关联关系来保存呢?
可以通过 @OneToOne() 指定 cascade 为 true

cascade 用来告诉 typeorm 当增删改一个 Entity 时,是否级联增删改它关联的 Entity。
这样只需要保存 idCard 就可以了。
查询

在 find 方法中通过 relations 来声明关联查询,反之不进行关联查询。

修改

指定 id 就是修改,不指定 id 就是新增。

删除
因为前面设置的级联关系是 cascade,所以只要删除了 user,那关联的 idCard 就会跟着被删除。

ts
const users = await AppDataSource.manager.find(User)
console.log('删除前查询: ', users)
await AppDataSource.manager.delete(User, 1)
const usersAfterDelete = await AppDataSource.manager.find(User)
console.log('删除后查询: ', usersAfterDelete)
执行日志
