一種巧妙的對象映射關係設計--JSON-ORM

項目介紹

這是標準數據庫封裝的上半部分,智能查詢(JSON-ORM)的實現。完整代碼:https://github.com/zhoutk/gels

設計思路

我們通用的ORM,基本模式都是想要脫離數據庫的,幾乎都在編程語言層面建立模型,由程序去與數據打交道。雖然脫離了數據庫的具體操作,但我們要建立各種模型文檔,用代碼去處理表之間的關係等等操作,讓初學者一時如墜雲霧。我的想法是,將關係數據庫擁有完善的設計工具之優勢與微服務結合起來,數據設計提供結構信息;前端送到後端的json對象自動映射成爲標準的SQL查詢語句,只要我們學習會標準的SQL語言,我們就能夠完成數據查詢。我的這種ORM方式,服務端不需要寫一行代碼,只需完成關係數據庫的設計,就能爲前端提供標準服務接口。並且遵循一套統一的接口(已經實踐檢驗,滿足百分之九九的查詢需求)來實現數據庫封裝,達到業務層可以隨意切換數據庫的目的。

數據庫查詢操作接口。

export default interface IDao {
    select(tablename: string, params: object, fields?: Array<string>): Promise<any>;                            //自動生成sql語句
    execSql(sql: string, values: Array<any>, params: object, fields?: Array<string>): Promise<any>;             //執行手動sql語句
}

智能查詢(JSON-ORM)

查詢保留字:fields, page, size, sort, search, lks, ins, ors, count, sum, group
  • fields, 定義查詢結果字段,支持數組和逗號分隔字符串兩種形式
    由前端來確定返回的數據庫字段信息,這樣後端的設計可以適用面更廣泛,而不會造成網絡帶寬的浪費。
    在KOA2的框架下,GET請求要支持輸入數組,只能把同一個key多次輸入,如:age=11&age=22。這樣很不方便,我實現了一個參數轉換函數,針對數組提供多種輸入形式。
    arryParse

        arryParse(arr): Array<any>|null {                      //返回值爲數據或空值
            try {
                if (Array.isArray(arr) || G.L.isNull(arr)) {   //如果輸入是數組或空,直接返回
                    return arr
                } else if (typeof arr === 'string') {          //若是字符串
                    if (arr.startsWith('[')) {                 //數組的字符串形式,進行轉換
                        arr = JSON.parse(arr)
                    } else {
                        //逗號拼接的字符串,mysql的驅動同時支持參數以字符串形式或數組形式提供,所以這裏可以不加判斷,直接用split函數將字符串轉化爲數組
                        arr = arr.split(',')                   
                    }
                }
            } catch (err) {
                arr = null            //數組的字符串形式轉換失敗,劉明輸入參數是錯誤的
            }
            return arr
        }

    查詢示例:

    請求URL:  /rs/users?username=white&age=22&fields=["username","age"]
    生成sql:   SELECT username,age FROM users  WHERE username = ?  and age = ?
  • page, size, sort, 分頁排序
    在mysql中這比較好實現,limit來分頁是很方便的,排序只需將參數直接拼接到order by後就好了。
    查詢示例:

    請求URL:  /rs/users?page=1&size=10&sort=age desc
    生成sql:   SELECT * FROM users  ORDER BY age desc LIMIT 0,10
  • search, 模糊查詢切換參數,不提供時爲精確匹配
    提供字段查詢的精確匹配與模糊匹配的切換,實現過程中,注意參數化送入參數時,like匹配,是要在參數兩邊加%,而不是在佔位符兩邊加%。
    另外,同一個字段匹配兩次模糊查詢,需要特別處理,我提供了一種巧妙的方法:

    value = pool.escape(value).replace(/\', \'/g, "%' and " + key + " like '%")   //將值用escape編碼,數組將轉化爲逗號連接的字符串,用正則全局替換,變成and連接
    value = value.substring(1, value.length - 1)                                  //去掉兩頭多餘的引號
    where += key + " like '%" + value + "%'"                                      //補齊條件查詢語句,這種方式,比用循環處理來得快捷,它統一了數組與其它形式的處理方式

    查詢示例

    請求URL:  /rs/users?username=i&password=1&search
  • ins, lks, ors
    這是最重要的三種查詢方式,如何找出它們之間的共同點,減少冗餘代碼是關鍵。

    - ins, 數據庫表單字段in查詢,一字段對多個值,例:
        查詢示例:
    請求URL:  /rs/users?ins=["age",11,22,26]
    生成sql:   SELECT * FROM users  WHERE age in ( ? )
    ```
    • ors, 數據庫表多字段精確查詢,or連接,多個字段對多個值,支持null值查詢,例:
      查詢示例:

      請求URL:  /rs/users?ors=["age",1,"age",22,"password",null]
      生成sql:   SELECT * FROM users  WHERE  ( age = ?  or age = ?  or password is null )
    • lks, 數據庫表多字段模糊查詢,or連接,多個字段對多個值,支持null值查詢,例:
      查詢示例:

      請求URL:  /rs/users?lks=["username","i","password",null]
  • count, sum
    這兩個統計求和,處理方式也類似,查詢時一般要配合group與fields使用。

    • count, 數據庫查詢函數count,行統計,例:
      查詢示例:

      請求URL:  /rs/users?count=["1","total"]&fields=["username"]
      生成sql:   SELECT username,count(1) as total  FROM users
    • sum, 數據庫查詢函數sum,字段求和,例:
      查詢示例:

      請求URL:  /rs/users?sum=["age","ageSum"]&fields=["username"]
  • group, 數據庫分組函數group,例:
    查詢示例:

請求URL:  /rs/users?group=age&count=["*","total"]&fields=["age"]
生成sql:   SELECT age,count(*) as total  FROM users  GROUP BY age
```
不等操作符查詢支持

支持的不等操作符有:>, >=, <, <=, <>, =;逗號符爲分隔符,一個字段支持一或二個操作。
特殊處:使用"="可以使某個字段跳過search影響,讓模糊匹配與精確匹配同時出現在一個查詢語句中

  • 一個字段一個操作,示例:
    查詢示例:

    請求URL:  /rs/users?age=>,10
    生成sql:   SELECT * FROM users  WHERE age> ?
  • 一個字段二個操作,示例:
    查詢示例:

    請求URL:  /rs/users?age=>,10,<=,35
    生成sql:   SELECT * FROM users  WHERE age> ? and age<= ?
  • 使用"="去除字段的search影響,示例:
    查詢示例:

    請求URL:  /rs/users?age==,22&username=i&search
    生成sql:   SELECT * FROM users  WHERE age= ?  and username like ?

相關視頻課程

運用typescript進行node.js後端開發精要
nodejs實戰之智能微服務快速開發框架
JSON-ORM(對象關係映射)設計與實現

資源地址

凝膠(gels)項目: https://github.com/zhoutk/gels
視頻講座資料: https://github.com/zhoutk/sifou
個人博客: https://github.com/zhoutk/blog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章