在 TypeORM 中,Repository
、EntityManager
、QueryBuilder
和 QueryRunner
都是用于操作数据库的不同工具,它们各自有独特的用途和适用场景。下面详细解释这些概念的区别:
Repository
Repository
是 TypeORM 为每个实体提供的一个抽象层。当你定义了一个实体类后,TypeORM 会自动为你创建一个对应的 Repository。例如,如果你有一个 User
实体,那么你就会有一个 UserRepository
。
特点:
- 类型安全:
Repository
的方法是针对特定实体类型的,可以智能提示实体属性和关系。 - 易于理解:对于简单的 CRUD 操作非常直观。
- 提供了基本的 CRUD 操作方法,如
save()
,findOne()
,find()
,remove()
等。
使用场景:
- 当你需要对单个实体进行简单的 CRUD 操作时。
- 对于小型项目或简单的业务逻辑。
EntityManager
EntityManager
是一个更通用的对象,用于执行实体的 CRUD 操作。它提供了对整个 ORM 功能的访问,包括事务管理和更复杂的查询功能。EntityManager
可以用于任何实体,并且允许你执行跨多个实体的操作。
特点:
- 灵活性高:可以用于任何实体类型。
- 支持更复杂的操作:如事务管理、批量操作等。
- 提供了更广泛的 API,如
createQueryBuilder()
,transaction()
等。
使用场景:
- 当你需要执行跨实体的操作时。
- 当你需要更复杂的事务管理时。
QueryBuilder
QueryBuilder
是 TypeORM 提供的一个高级 API,用于构建复杂的 SQL 查询。它允许你以类型安全的方式编写查询,从而减少错误并提高代码的可读性和可维护性。QueryBuilder
支持各种查询操作,包括但不限于 SELECT、INSERT、UPDATE 和 DELETE。
特点:
- 类型安全:
QueryBuilder
是基于实体类的,因此它可以智能提示实体属性和关系。 - 易于使用:通过链式调用方法,你可以逐步构建复杂的查询语句。
- 灵活:支持子查询、联接、分组、排序等各种 SQL 功能。
使用场景:
- 当你需要构建复杂的 SQL 查询时。
- 当你需要执行更复杂的查询逻辑时。
QueryRunner
QueryRunner
是一个用于事务管理的工具。它提供了一个环境,在这个环境中你可以手动执行原生的 SQL 查询或者使用 EntityManager
来执行操作。QueryRunner
在处理需要事务的场景时非常有用,例如执行一系列必须一起成功或一起失败的操作。
特点:
- 事务管理:
QueryRunner
提供了事务的开始、提交和回滚方法。 - 原始 SQL 执行:可以直接执行原生 SQL 查询。
- 隔离:每个
QueryRunner
都有自己的EntityManager
,可以独立于其他EntityManager
运行。
使用场景:
- 当你需要处理复杂的事务时。
- 当你需要直接执行原生 SQL 查询时。
示例
下面是一些使用 Repository
、EntityManager
、QueryBuilder
和 QueryRunner
的示例。
使用 Repository
import { getRepository } from "typeorm";
import { User } from "./entity/User";
const userRepository = getRepository(User);
async function findUserById(id: number) {
const user = await userRepository.findOne(id);
return user;
}
使用 EntityManager
import { EntityManager, createEntityManager } from "typeorm";
import { User } from "./entity/User";
async function findUserById(id: number) {
const manager: EntityManager = createEntityManager();
const user = await manager.findOne(User, id);
return user;
}
使用 QueryBuilder
import { getRepository } from "typeorm";
import { User } from "./entity/User";
async function findUsersByName(name: string) {
const userRepository = getRepository(User);
const users = await userRepository
.createQueryBuilder("user")
.where("user.name = :name", { name })
.getMany();
return users;
}
使用 QueryRunner
import { createConnection, Connection } from "typeorm";
import { User } from "./entity/User";
let connection: Connection;
async function main() {
// 建立数据库连接
connection = await createConnection();
// 创建一个新的 QueryRunner 实例
const queryRunner = connection.createQueryRunner();
try {
// 开始一个事务
await queryRunner.connect();
await queryRunner.startTransaction();
// 执行一些操作
const userRepository = queryRunner.manager.getRepository(User);
const newUser = new User();
newUser.name = "John Doe";
await userRepository.save(newUser);
// 提交事务
await queryRunner.commitTransaction();
} catch (error) {
// 如果出错,则回滚事务
await queryRunner.rollbackTransaction();
} finally {
// 释放 QueryRunner
await queryRunner.release();
}
}
main().catch(console.error);
总结
- Repository 适用于简单的 CRUD 操作,尤其是对于单个实体。
- EntityManager 提供了更多的灵活性,适用于跨实体的操作和事务管理。
- QueryBuilder 适用于构建复杂的查询,尤其是在需要组合多个表的情况下。
- QueryRunner 专门用于事务管理,可以执行原生 SQL 或者使用
EntityManager
的功能。
在实际应用中,你可能会根据具体的需求选择使用其中之一或者将它们结合使用。