数据库ORM及操作数据库的三层抽象概述(Node.js为例)
什么是ORM?
ORM框架:Object Relational Mapping,对象-关系-映射,所以说ORM框架就是用面向对象的方式和目前的关系型数据库做匹配。
为什么会有ORM?
它解决了对象和关系型数据库之间的数据交互问题。
1、业务代码中手写SQL容易出错
而有了 ORM 技术以后,只要提前配置好对象和数据库之间的映射关系,ORM 就可以自动生成 SQL 语句,并将对象中的数据自动存储到数据库中,整个过程不需要人工干预。 在 node 中,ORM 一般使用 类 或者注解来配置对象和数据库之间的映射关系。
2、字段类型的静态检查
Int number '2222'
比方我数据库定义了一个id字段类型为 Int
orm中定义为number, 假设我用orm操作数据库的时候id我传了字符串, 静态检查就会给我报错。
3、提高开发效率
orm避免了简单且重复的查询直接手写sql, 提高的开发效率。
4、缓存
比方我查网站首页一个东西,需求呢缓存1分钟, 那么orm也可以来帮我做,加个配置字段, 相同的sql就会缓存结果。
orm的缺点
ORM 在提高开发效率的同时,也带来了以下几个缺点:
- ORM 增加了大家的学习成本,为了使用 ORM 技术,您至少需要掌握一种 ORM 框架。
- 自送生成 SQL 语句会消耗计算资源,这势必会对程序性能造成一定的影响。
- 对于复杂的数据库操作,ORM 通常难以处理,即使能处理,自动生成的 SQL 语句在性能方面也不如手写的原生 SQL。
- 生成 SQL 语句的过程是自动进行的,不能人工干预,这使得开发人员无法定制一些特殊的 SQL 语句。
复杂sql示例 像如下需要关联多个表, 各种计算的复杂的查询,显然,orm是满足不了的, 这时候就需要手写。
static async getExtendOrderCommodity(uid, ordernos = null) {
let SQL = `
SELECT
a.orderno,
a.buy_num buyNum,
round(a.period * 365) AS period,
a.increase_capacity increaseCapacity,
b.commodityname,
b.power,
b.min_capacity minCapacity,
b.max_capacity maxCapacity,
d.start_at startAt,
DATE_ADD(d.start_at,INTERVAL a.period year) lastTime,
d.end_at endAt
FROM
order_info a
INNER JOIN commodity b ON a.commodityid = b.id
INNER JOIN order_related_sn c ON a.orderno = c.orderno
LEFT JOIN deposit d ON c.sn = d.sn
AND c.uid = d.uid
WHERE
a.uid = ?
AND b.expend_status = 1
AND c.deposit_status = 1
AND a.complete = 1
AND a.increase_capacity = 0
AND a.deleted_at IS NULL
`;
if (Array.isArray(ordernos)) {
SQL += ` AND a.orderno IN (${ordernos.join(',')})`;
}
SQL += ` GROUP BY a.orderno`;
const result = await sequelize.query(SQL, {
replacements: [uid],
type: sequelize.QueryTypes.SELECT,
logging: false,
});
return result;
}
数据库与对象之间的映射关系
数据库 | 类/对象 |
---|---|
表(table) | 类(class) |
表中的记录(record,也称行) | 对象(object) |
表中的字段(field,也称列) | 对象中的属性(attribute) |
操作数据库的三层抽象
由高到低
1、ORM
高层抽象:ORM,建立模型对象到关系型数据库的映射,之后,对模型对象的操作自动映射到数据库中
// select "name" from "users" where "id" = 9527
class User extend Sequlize {
id
}
User.findOne({
where: {
id: 9527
}
})
2、SQL query builder
中层抽象:SQL Query Builder,生成操作指令。
这一层可以理解为sql构造器,就是你把条件给好,什么表查什么字段,什么条件,它帮你拼接SQL。
但是至于有没有这张表、这个字段, 他是不会感知的,因为他没有关系映射。
例如nodejs中的 knex。
knex.select('name').from('users').where('id', '=', 9527)
//select "name" from "users" where "id" = 9527
3、原生SQL
底层抽象:Database Driver,连接数据库并与之通信,发出操作指令,取回操作结果。
select "name" from "users" where "id" = 9527
操作数据库的控制力和生产力关系图
1、传统的ORM框架虽然生产力高但是可控性低
能满足大部分一般的查询,复杂的需要手写
2、原生SQL语句虽然完全可控但是生产力低
什么意思 自由度高,完全自己控制,但是因为是字符串容易出错,不好排查问题,所以生产力低下。
3、其他SQL查询生成器高可控,中等生产力。
最后
ORM这个东西是属于语言层面的,每个语言都有自己的ORM的实现。
但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。但我们不能指望工具能一劳永逸的解决所有问题,有些问题还是需要特殊处理的,但需要特殊处理的部分对绝大多数的系统,应该是很少的, 对于大部分应用,orm都大大提高了我们开发效率。
小伙伴们都怎么看呢?
转载自:https://juejin.cn/post/7243240618788814906