1. 介绍
TypeORM 是一个用于 Node.js 的 ORM(Object-Relational Mapping,对象关系映射)库,它提供了一种将 JavaScript 对象映射到数据库表的方式。这意味着你可以使用 JavaScript 对象和 TypeScript 类来与数据库进行交互,而不必编写原始的 SQL 语句。
以下是 TypeORM 的一些关键特性:
- 类型安全:由于 TypeORM 支持 TypeScript,它允许你在开发时获得类型检查的好处。
- 数据库支持:TypeORM 支持多种数据库系统,包括 MySQL, PostgreSQL, SQLite, Microsoft SQL Server, Oracle, 和 MongoDB(通过一个单独的 MongoDB 驱动)。
- 实体和关系:你可以定义实体类来表示数据库中的表,并且可以轻松地定义实体之间的关系,如一对一、一对多和多对多。
- 高级功能:TypeORM 提供了事务、迁移、复用数据库连接、复杂查询等高级功能。
- 查询构建器:它提供了一个强大的查询构建器,允许你构建复杂的查询而不必手写 SQL。
- 懒加载:支持懒加载和急切加载,以优化应用程序的性能。
- 可定制性:TypeORM 允许你自定义实体的列映射、表名、列名等。
- 活跃记录模式:TypeORM 支持数据映射模式,包括数据映射和活跃记录模式。
- 装饰器:使用 TypeScript 的装饰器语法,TypeORM 允许你以声明式的方式定义实体和列。
- 集成:TypeORM 可以很容易地集成到现有的 Node.js 应用程序中,并且与许多流行的框架(如 Express.js)协同工作。
TypeORM 的使用通常涉及以下步骤:
- 定义实体:创建 TypeScript 类,使用 TypeORM 提供的装饰器来定义实体属性和数据库表的映射关系。
- 建立连接:配置并建立与数据库的连接。
- 执行操作:使用 TypeORM 的 API 来执行 CRUD(创建、读取、更新、删除)操作。
- 迁移:使用迁移来自动更新数据库结构以匹配你的实体定义。
TypeORM 是一个功能强大的库,适用于希望在 Node.js 应用程序中使用 ORM 功能的开发者。
2. 项目创建
2.1. 创建一个typeorm项目
npx typeorm init --name MyProject --database mysql
他生成的项目结构
2.2. 创建个容器
services:
mysql8:
image: mysql:8.0
restart: always
# 设置默认的认证插件为mysql_native_password
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: root
ports:
# 映射为 13311端口
- '13311:3306'
在当前目录下执行docker-compose up,然后打开你的Docker Desktop,你就会发现,多了一个容器,绿色代表正常运行
2.3. 创建一个数据库
我这台电脑上安装的可视化工具是DBeaver,这里我就用DBeaver给大家演示(后面如果我在另外一台电脑上操作的话,会用navicat)
点击这个数据库,在点击 新建数据库连接
选择mysql,在下一步
注意:这个端口,它默认是3306,但是我们上面写的那个容器配置,是映射到13311的(主要是我电脑会开很多mysql配置,所以我就重新映射了端口),密码也是我们上面自己写的那个密码,点击测试,没问题就点击完成。
鼠标右击这个数据库,点击新建数据库
输入个数据库名,其他就 用默认的就行,点击确定,数据库就创建成功了
3. 创建表
我们现在回到我们的项目中
pnpm install mysql2
pnpm start
他就会给我们去创建表
这就是他生成的表和数据(记得在表上鼠标右键,然后点刷新)
他建表的依据是根据我们实体来的
默认生成的数据是在index.ts中,它给我们写的
4. 创建实体
实体是映射到数据库表(或使用 MongoDB 时的集合)的类。你可以通过定义一个新类来创建一个实体,并用 @Entity() 标记它:
我们新建一个实体,来看看我们如何写一个建表的实体类
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
// @Entity指定它是一个 Entity
@Entity({
name: 't_aaa' // 自己定义表名
})
export class Aaa {
// @PrimaryGeneratedColumn()指定主键,并且自动生成
@PrimaryGeneratedColumn({
comment: '主键id' // 添加注释
})
id: number
// @Column() 映射属性和字段的对应关系
@Column({
name: 'user_name', // 自定义字段名
unique: true, // 添加唯一约束
type: 'varchar', // 设置字段类型
length: 20, // 设置字段长度
comment: '姓名' // 添加注释
})
name: string
@Column({
type: 'double',
})
height: number
}
type 数据库里的数据类型
我们再去引用下Aaa
pnpm start
更多实体内容请参考:typeorm.nodejs.cn/entities
5. crud
5.1. 增
save的方式
pnpm start
批量新增
inset 方式
5.2. 改
save的方式
我们的save不仅可以新增还可以修改,你指定了主键,他就变成修改
运行后,可以看到他会先查询在修改。
那我们给个不存在的id呢?
可以看到id没在数据库里时,他就会变成新增
批量修改
update的方式
那我们给个不存在的id呢?
可以看到这种是不会给我们新增进去的
批量修改
5.3. 查
查单个
还可以
还可以查不到时就报错
他找不到时会抛一个 EntityNotFoundError 的异常
查所有
条件查询多个
查数量
你还可以指定条件
5.4. 删
批量删
remove的删除
5.5. 执行原生sql
5.6. queryBuilder
import { AppDataSource } from "./data-source"
import { User } from "./entity/User"
AppDataSource.initialize().then(async () => {
// createQueryBuilder() 是 TypeORM 提供的一个方法,用于创建一个新的查询构建器实例,允许你以一种流畅和声明式的方式构建 SQL 查询。
const queryBuilder = await AppDataSource.manager.createQueryBuilder();
// select("user") 指定了你想从数据库中选择的字段
// from(User, "user") 指定了查询的来源,即你想从哪个实体(或表)中选择数据。User 是实体类的名称,而 "user" 是为这个实体指定的别名。
// where("user.age = :age", { age: 26 }) 定义了一个查询条件,即选择 age 字段等于 26 的记录。:age 是一个参数占位符,后面的对象 { age: 26 } 提供了实际的参数值。
// getOne() 是查询构建器的一个方法,用于执行构建的查询并返回结果。由于使用了 getOne(),所以查询结果应该是单个对象,而不是一个对象数组。
const user = await queryBuilder.select("user")
.from(User, "user")
.where("user.age = :age", { age: 26 })
.getOne();
console.log(user);
}).catch(error => console.log(error))
5.7. getRepository
之前我们都是通过参数指定的实体,如:
我们还可以 使用 getRepository