ORM(对象关系映射)

1. 什么是 ORM

ORM(Object Relational Mapping)

中文:

对象关系映射

它是一种将关系型数据库面向对象编程语言进行映射的技术。

简单来说:

复制代码
复制代码
操作数据库
=
操作对象

而不是直接编写 SQL。


传统方式

SQL:

复制代码
复制代码
SELECT * FROM users WHERE id = 1;

Node.js:

复制代码
复制代码
const result = await connection.query(
  'SELECT * FROM users WHERE id = 1'
);

ORM方式

复制代码
复制代码
const user = await userRepository.findOne({
  where: {
    id: 1
  }
});

开发者操作的是对象。

ORM 自动生成 SQL。


2. ORM 的核心思想

ORM 本质上是一层映射关系。

数据库与对象的映射

数据库 ORM
Database 数据库
Table 类(Class)
Row 对象(Object)
Column 属性(Property)
Primary Key 主键字段
Foreign Key 对象关联

例如:

数据库表:

复制代码
复制代码
users
id name age
1 Tom 20

对应:

复制代码
复制代码
class User {
  id: number;
  name: string;
  age: number;
}

数据库记录:

复制代码
复制代码
1 Tom 20

映射为:

复制代码
复制代码
{
  id:1,
  name:'Tom',
  age:20
}

3. ORM 的工作原理

以查询用户为例:

复制代码
复制代码
const user = await userRepository.findOne({
  where: { id: 1 }
});

执行流程:

复制代码
复制代码
代码
 ↓
ORM
 ↓
生成SQL
 ↓
数据库执行
 ↓
返回结果
 ↓
转换对象
 ↓
返回程序

生成的 SQL:

复制代码
复制代码
SELECT *
FROM users
WHERE id = 1;

4. ORM 解决了什么问题

问题1:SQL编写繁琐

传统:

复制代码
复制代码
const sql =
`
SELECT *
FROM users
WHERE age > 18
`;

大量业务代码中:

复制代码
复制代码
SQL
SQL
SQL
SQL
SQL

难维护。


问题2:数据库切换困难

假设:

复制代码
复制代码
MySQL
↓
PostgreSQL

SQL语法可能不同。

ORM封装后:

复制代码
复制代码
userRepository.find()

代码几乎不用改。


问题3:对象与数据转换

传统:

复制代码
复制代码
const result = await query(...)

const user = {
  id: result[0].id,
  name: result[0].name
}

ORM自动完成转换。


5. ORM 常见操作

查询

复制代码
复制代码
await userRepository.find()

SQL:

复制代码
复制代码
SELECT * FROM users;

条件查询

复制代码
复制代码
await userRepository.find({
  where:{
    age:18
  }
})

SQL:

复制代码
复制代码
SELECT *
FROM users
WHERE age = 18;

插入

复制代码
复制代码
await userRepository.save({
  name:'Tom',
  age:20
})

SQL:

复制代码
复制代码
INSERT INTO users(name,age)
VALUES('Tom',20);

更新

复制代码
复制代码
await userRepository.update(
  1,
  {
    age:30
  }
)

SQL:

复制代码
复制代码
UPDATE users
SET age = 30
WHERE id = 1;

删除

复制代码
复制代码
await userRepository.delete(1)

SQL:

复制代码
复制代码
DELETE FROM users
WHERE id = 1;

6. ORM 的核心组成

Entity(实体)

实体对应数据库表。

TypeORM:

复制代码
复制代码
@Entity()
export class User {

  @PrimaryGeneratedColumn()
  id:number;

  @Column()
  name:string;

}

对应:

复制代码
复制代码
CREATE TABLE users(
  id INT,
  name VARCHAR(255)
)

Repository(仓库)

负责增删改查。

复制代码
复制代码
@InjectRepository(User)
private userRepository: Repository<User>;

使用:

复制代码
复制代码
this.userRepository.find()

Migration(迁移)

用于管理数据库结构变化。

例如:

复制代码
复制代码
新增字段
修改字段
删除字段

通过迁移同步数据库。


Relationship(关系映射)

管理表之间关系。

例如:

复制代码
复制代码
用户
↓
订单

7. ORM中的关系映射

一对一(One To One)

例如:

复制代码
复制代码
用户
↔
身份证
复制代码
复制代码
@OneToOne()

一对多(One To Many)

例如:

复制代码
复制代码
用户
↓
订单

一个用户多个订单。

复制代码
复制代码
@OneToMany()

多对一(Many To One)

复制代码
复制代码
订单
↓
用户

多个订单属于一个用户。

复制代码
复制代码
@ManyToOne()

多对多(Many To Many)

例如:

复制代码
复制代码
学生
↔
课程

一个学生多门课。

一门课多个学生。

复制代码
复制代码
@ManyToMany()

8. ORM 常见框架

Node.js

TypeORM

特点:

复制代码
复制代码
NestJS官方推荐
装饰器丰富
学习简单

示例:

复制代码
复制代码
await repository.find()

Prisma

目前最火。

特点:

复制代码
复制代码
类型安全
自动生成TS类型
性能较好

示例:

复制代码
复制代码
await prisma.user.findMany()

Sequelize

老牌ORM。

复制代码
复制代码
User.findAll()

9. TypeORM 与 Prisma 对比

对比项 TypeORM Prisma
学习成本
类型安全 一般
NestJS支持 官方示例多 很好
社区成熟度
自动生成类型
性能 一般 较好
推荐程度 ★★★★ ★★★★★

10. ORM 的优点

提高开发效率

不用频繁写 SQL。

复制代码
复制代码
userRepository.save(user)

即可完成保存。


面向对象

符合开发习惯。

复制代码
复制代码
user.name = 'Tom'

而不是:

复制代码
复制代码
UPDATE ...

减少重复代码

CRUD操作统一。


降低 SQL 注入风险

ORM自动处理参数。

例如:

复制代码
复制代码
find({
  where:{
    name:input
  }
})

自动参数化。


提高代码可维护性

数据库逻辑集中管理。


11. ORM 的缺点

性能损耗

ORM:

复制代码
复制代码
user.posts.comments.author

可能生成大量 SQL。


学习成本

需要学习:

复制代码
复制代码
实体
关系映射
Repository
QueryBuilder
Migration

复杂查询不方便

例如:

复制代码
复制代码
GROUP BY
UNION
窗口函数
复杂JOIN

ORM写法反而更复杂。


N+1 问题

例如:

复制代码
复制代码
查询100个用户
↓
查询100次订单

最终:

复制代码
复制代码
1 + 100
=
101次SQL

性能极差。


12. ORM 与 SQL 的关系

很多新人误解:

复制代码
复制代码
学ORM
=
不用学SQL

这是错误的。

正确理解:

复制代码
复制代码
SQL
↓
基础
↓
ORM
↓
高级封装

真正的后端开发:

复制代码
复制代码
70%
ORM

20%
Query Builder

10%
原生SQL

复杂统计分析依然离不开 SQL。


13. NestJS 中的 ORM

最常见架构:

复制代码
复制代码
Controller
    ↓
Service
    ↓
Repository(TypeORM)
    ↓
MySQL

示意图:

复制代码
复制代码
HTTP请求
    ↓
Controller
    ↓
Service
    ↓
TypeORM
    ↓
MySQL

14. 面试必背总结

什么是 ORM?

ORM(Object Relational Mapping)是一种对象关系映射技术,它建立了程序对象与数据库表之间的映射关系,使开发者能够通过操作对象完成数据库操作,而无需直接编写大量 SQL。


ORM 的核心映射关系?

复制代码
复制代码
Table  ↔ Class
Row    ↔ Object
Column ↔ Property

ORM 的优点?

复制代码
复制代码
提高开发效率
减少SQL编写
面向对象开发
降低SQL注入风险
提高可维护性

ORM 的缺点?

复制代码
复制代码
性能开销
复杂查询困难
存在N+1问题
需要理解底层SQL

NestJS 常用 ORM?

复制代码
复制代码
TypeORM
Prisma

其中:

复制代码
复制代码
TypeORM = 官方教程常用

Prisma = 当前企业新项目趋势

一句话记忆:

ORM 就是数据库和程序对象之间的翻译官,让开发者用操作对象的方式完成数据库操作。