假设我有主表 Users 和参考表 UserRoles,这样每个用户都有一个角色保存在 roleId 列中,每个角色都有一个 id 和一个描述。
如果我想插入一个具有管理员角色的新用户,则可以使用以下 SQL 查询:
INSERT INTO `users` (`name`, `roleId`)
VALUES ('John Doe', (SELECT `id` FROM `roles` WHERE `roles`.`description` = 'admin'));
如何在具有两个实体用户和角色的 TypeORM 中复制相同的内容?
我知道我可以做到以下几点:
const adminRole = await Role.findOne({description: 'admin'});
const newUser = User.create({name: 'John Doe'});
newUser.role = adminRole;
await newUser.save();
但这相当于将角色选择到变量中,然后在插入期间使用该变量。有没有一种方法可以将其压缩为一个查询,以便数据库仅被命中一次?
我知道我可以创建一个具有这样关系的用户
User.create({name: 'John Doe', role: {id: 1}});
但我需要知道这个的 id。如果我把名字写成下面这样
User.create({name: 'John Doe', role: {name: 'admin'}});
我收到以下错误
Error: Cannot find alias for relation at type
,因为我尚未加载关系。
我在这里找到了有关如何制作 INSERT INTO SELECT 语句的信息,但这是整个插入来自选择的地方,而不仅仅是特定列。
有没有办法模拟这个插入查询?或者我被迫分两步完成(或尽可能多的参考列)或使用查询生成器?
提前谢谢你
TypeOrm 不允许开箱即用,但是您可以通过两种方式实现这一点
const role = await getConnection()
.createQueryBuilder()
.select('role')
.from(Role, 'role')
.where('role.description = :description', { description: 'admin' })
.getOne();
if (!role) {
console.error('Role not found');
return;
}
const newUser = User.create({ name: 'John Doe', role });
这种方法将保持原子性完整,并且一次性执行完整的操作(实际上可能看起来我们多次访问数据库,但在 typeorm 的底层将它们编译为要执行的单个查询)
import { getManager, getRepository } from 'typeorm';
import { User } from './entity/User';
import { Role } from './entity/Role';
async function createUserWithRole() {
const entityManager = getManager();
const roleRepository = getRepository(Role);
try {
await entityManager.transaction(async transactionalEntityManager => {
const adminRole = await roleRepository.findOneOrFail({ description: 'admin' });
const newUser = transactionalEntityManager.create(User, { name: 'John Doe', role: adminRole });
await transactionalEntityManager.save(newUser);
});
console.log('User created successfully with role.');
} catch (error) {
console.error('Error creating user with role:', error);
}
}
createUserWithRole();