这节继续学习 TypeORM 的一对多关系映射和对应的 CRUD。
前置工作
- 创建 typeorm 项目
npx typeorm@latest init --name typeorm_one_to_more_relation_mapping --database mysql
- 安装 mysql2 驱动包
npm i mysql2
- 修改 data-source.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_test",
synchronize: true,
logging: true,
entities: [User],
migrations: [],
subscribers: [],
poolSize: 10,
connectorPackage: 'mysql2',
extra: {
authPlugin: 'sha256_password'
}
})
具体参数配置解释可见之前的文章: TypeORM 基础篇:项目初始化与增删改查全流程。
创建部门 department 和员工 employee 两个实体
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"
@Entity()
export class Department {
@PrimaryGeneratedColumn()
id: number
@Column({
length: 100
})
name: string
}
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"
@Entity()
export class Employee {
@PrimaryGeneratedColumn()
id: number
@Column({
length: 100
})
name: string
}
把这两个实体放到 data-source 的 entities 属性中:
删除 User 实体以及 index.ts 中相关代码。
import { AppDataSource } from "./data-source"
AppDataSource.initialize().then(async () => {
console.log('...')
}).catch(error => console.log(error))
添加一对多映射
1. 在 “多” 的一方 通过 @ManyToOne 装饰器 添加。
import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"
import {Department} from "./Department";
@Entity()
export class Employee {
@PrimaryGeneratedColumn()
id: number
@Column({
length: 100
})
name: string
@ManyToOne(() => Department, {
cascade: true // 级联保存
})
department: Department
}
在 index.ts 中增加一些数据:
import { AppDataSource } from "./data-source"
import {Department} from "./entity/Department";
import {Employee} from "./entity/Employee";
AppDataSource.initialize().then(async () => {
const dept1 = new Department()
dept1.name = '产品部'
const em1 = new Employee()
em1.name = '三十1'
em1.department = dept1
const em2 = new Employee()
em2.name = '三十2'
em2.department = dept1
const em3 = new Employee()
em3.name = '三十3'
em3.department = dept1
const em4 = new Employee()
em4.name = '三十4'
em4.department = dept1
// await AppDataSource.manager.save(dept1)
// 因为设置了 cascade: true,所以这里只需要保存员工即可,部门会自动保存
await AppDataSource.manager.save([em1, em2, em3, em4])
}).catch(error => console.log(error))
执行 npm run start 即可创建对应的表和关系。
2. 在 “一”的一方 通过 @OneToMany 装饰器添加
先将 Employee 实体中的 cascade: true 去掉,避免两个表都级联保存导致无限保存。
import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm"
import {Employee} from "./Employee";
@Entity()
export class Department {
@PrimaryGeneratedColumn()
id: number
@Column({
length: 100
})
name: string
@OneToMany(() => Employee, (employee) => employee.department, {
cascade: true
})
employees: Employee[]
}
通过 OneToMany 装饰器的第二个参数指定外键列在 employee.department 维护。
修改 index.ts:
import { AppDataSource } from "./data-source"
import {Department} from "./entity/Department";
import {Employee} from "./entity/Employee";
AppDataSource.initialize().then(async () => {
const em1 = new Employee()
em1.name = '三十11'
const em2 = new Employee()
em2.name = '三十22'
const em3 = new Employee()
em3.name = '三十33'
const em4 = new Employee()
em4.name = '三十44'
const dept1 = new Department()
dept1.name = '研发部'
dept1.employees = [em1, em2, em3, em4]
await AppDataSource.manager.save(dept1)
}).catch(error => console.log(error))
执行 npm run start:
关联查询
import { AppDataSource } from "./data-source"
import {Department} from "./entity/Department";
import {Employee} from "./entity/Employee";
AppDataSource.initialize().then(async () => {
// 关联查询
const deptList = await AppDataSource.manager.find(Department, {
relations: {
employees: true
}
})
console.log(deptList)
}).catch(error => console.log(error))
执行 npm run start
删除
设置级联关系
删除 Department 之前,需要先把关联的 Employee 删除掉;如果设置了级联关系则可以省略这一步,只要删了 Department,mysql 会自动把关联的 Employee 记录删除,或者是把它们的外键 id 置为空。
import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"
import {Department} from "./Department";
@Entity()
export class Employee {
@PrimaryGeneratedColumn()
id: number
@Column({
length: 100
})
name: string
@ManyToOne(() => Department, {
// cascade: true // 级联保存
onDelete: 'CASCADE'
})
department: Department
}
在 index.ts 中增加删除
import { AppDataSource } from "./data-source"
import {Department} from "./entity/Department";
import {Employee} from "./entity/Employee";
AppDataSource.initialize().then(async () => {
await AppDataSource.manager.delete(Department, 1);
const deptListAfterDelete = await AppDataSource.manager.find(Department, {
relations: {
employees: true
}
})
console.log(deptListAfterDelete)
}).catch(error => console.log(error))
执行 npm run start