裡面如何建立新的module_如何實現一個簡易的orm
技術標籤:裡面如何建立新的module
什麼是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