什么是orm?
ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写。不负责任的总结就是通过类似对象管理的模式,来管理数据库,来避免直接操作数据库,降低数据库的学习成本。
如果还是不懂? 可以直接看看阮一峰的这篇文章 ORM实例教程
现有基于Node的ORM
- sequelize
- openrecord
为什么要造轮子?
- 了解某些语法是怎样实现的
- 巩固基础
- 构造自己更满意的语法糖
- 好玩
所以这篇文章比较适合有这些相同想法的同学阅读,并且整篇文章会比较基础,大佬们可以在这里止步了。
功能设计
要实现一个功能库,首先我们得设计我们有哪些功能,回忆下大学数据库课程里面的那几个大流程,我们要做的也不尽相同。
- 连接
- 增
- 删
- 改
- 查
连接
连接当然是我们orm的最基础的功能,所以我们设计如下:
module.exports.connect = config => {
// create sql pool connect
}
一个对外暴露的config, 本质上就是将创建连接池所需参数对外再暴露一次,并且加上一些自己想要定制的参数即可。
比如我这里是有个debug模式,开启后会输出所有执行的sql语句,当然你也可以再这里埋一些callback,用于实现获取记录日志的能力。
{
limit: : 10,
host : '127.0.0.1',
port : '3306',
user : 'root',
password : 'root',
database : 'test',
debug : true
}
具体连接池怎么创建的就不说了,看看mysql的文档就行了,唯一要记得就是用单例模式创建连接,每次sql操作结束后记得释放connect就行
增,删,改,查
说白了这4个就是我们最核心的操作,但是如何设计呢?
看看相关的orm库就知道了,每张表都看成一个对象,增删改查是他的属性方法,所以既然是orm,我们当然要把他设计成对象的操作模式,如下:
module.exports.model = data => {
// return new instance
}
const student = orm.model(data)
我们在model 函数初始化时会给它传一些参数,比如表名,状态,表字段,主键字段等,让他初始化的时候可以存储起来,最后再返回一个新的实例,比如下面这样:
const student = orm.model('student', {
name: String,
sex: Number
})
然后model上就会有很多我们想要的属性方法,并且每一类方法都对应一类sql,这样就可以实现我们的增,删,改,查了。
student.create()
student.find()
student.where()
student.update()
student.delete()
// create sql demo
create(data) {
const keys = Object.keys(data).join(',')
const values = Object.values(data).map(d => escape(d)).join(',')
const SQL = `insert into ${table} (${keys}) VALUES (${values})`
}
结束或许是新的开始
到这里大家根据上面的伪代码,应该可以创建一个最基础的伪orm,勉勉强强的可以满足你大部分基础操作(当然我相信你在整合这些方法的时候一定会踩更多的坑,如果需要帮助可以看看我的实现)。
这里再回到我们之前提的“为什么要造轮子”,上面介绍的只是一些实现的大致流程和基础的回顾。
但是如何构造我们更满意的语法糖?如何更好玩?
比如下面的代码:
(async () => {
console.log(await orm.Model('Post')) // 获取到post表的数据
console.log(await orm.Model('Post').find(1)) // 获取到post表里id=1的数据
})()
所以在最后抛出一个问题,如何实现上述的这种类似惰性的链式调用功能?
下面是我的实现方案:
yuanhaoyu/h-ormgithub.com