TypeORM @ManyToMany() 使用示例
TypeORM 中的 @ManyToMany 装饰器用于定义多对多关系。下面是一个简单的示例:
假设我们有两个实体,一个是用户(User),一个是角色(Role),它们之间有多对多关系。一个用户可以有多个角色,一个角色可以被多个用户拥有。
首先,我们需要在 User 实体和 Role 实体之间使用 @ManyToMany 装饰器来定义多对多关系,同时还需要使用 @JoinTable 装饰器来指定关联表的名称和字段
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import { Role } from './Role';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => Role, role => role.users)
@JoinTable()
roles: Role[];
}
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany } from 'typeorm';
import { User } from './User';
@Entity()
export class Role {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => User, user => user.roles)
users: User[];
}
上面的代码定义了 User 和 Role 实体之间的多对多关系。@ManyToMany 装饰器中,第一个参数是关联实体的类型,第二个参数是反向关联字段。
@startuml
!theme plain
top to bottom direction
skinparam linetype ortho
class role {
name: varchar(255)
id: int
}
class user {
name: varchar(255)
id: int
}
class user_roles_role {
userId: int
roleId: int
}
user_roles_role -[#595959,plain]-^ role : "roleId:id"
user_roles_role -[#595959,plain]-^ user : "userId:id"
@enduml
使用这些实体,我们可以通过创建和查询用户、角色和它们之间的关联来管理多对多关系。例如,下面的代码演示了如何创建一个用户和一个角色,并将它们关联起来。
const role1 = roleRepo.create({ name: 'role1' });
const role2 = roleRepo.create({ name: 'role2' });
await roleRepo.save([role1, role2]);
const user1 = userRepo.create({ name: 'user1', roles: [role1] });
const user2 = userRepo.create({ name: 'user2', roles: [role1, role2] });
await userRepo.save([user1, user2]);
const foundUser1 = await userRepo.findOne({ where: { name: 'user1' }, relations: ['roles'] });
const foundUser2 = await userRepo.findOne({ where: { name: 'user2' }, relations: ['roles'] });
console.log("foundUser1 :",foundUser1);
console.log("foundUser2 :",foundUser2);
output
foundUser1 : User { id: 1, name: 'user1', roles: [ Role { id: 1, name: 'role1' } ] }
foundUser2 : User {
id: 2,
name: 'user2',
roles: [ Role { id: 1, name: 'role1' }, Role { id: 2, name: 'role2' } ]
}
在 TypeORM 中,当你从数据库中检索实体时,你可以使用 relations 属性来指定要同时加载的关联实体。
在这个例子中,relations: ['roles'] 的作用是告诉 TypeORM 要同时加载每个用户的角色信息。由于用户和角色是多对多的关联关系,因此加载这些关联实体需要执行额外的查询。使用 relations 属性可以确保这些关联实体也被加载,以便在后续的代码中可以访问它们。
查找角色为 role1 的所有用户
你可以使用 typeorm 的查询构建器(query builder)来查找角色为 role1 的所有用户,例如:
// 查找角色为 role1 的所有用户
const role1Users = await userRepo
.createQueryBuilder('user')
.innerJoin('user.roles', 'role')
.where('role.name = :roleName', { roleName: 'role1' })
.getMany();
这会返回所有具有 role1 角色的用户。