c++關係數據庫訪問通用接口設計(JSON-ORM c++版)

重操C++舊業,習慣一般的數據庫操做方式,所以抽時間,把JSON-ORM封裝了一個C++版,現支持sqlit3與mysql,postgres已經作好了準備。前端

設計思路

咱們通用的ORM,基本模式都是想要脫離數據庫的,幾乎都在編程語言層面創建模型,由程序去與數據庫打交道。雖然脫離了數據庫的具體操做,但咱們要創建各類模型文檔,用代碼去寫表之間的關係等等操做,讓初學者一時如墜雲霧。個人想法是,將關係數據庫擁有的完善設計工具之優點,來實現數據設計以提供結構信息,讓json對象自動映射成爲標準的SQL查詢語句。只要咱們理解了標準的SQL語言,咱們就可以完成數據庫查詢操做。node

技術選擇

json庫

JSON-ORM 數據傳遞採用json來實現,使數據標準能從最前端到最後端進行和諧統一。我選擇了rapidjson,但rapidjson爲了執行效率,直接操做內存,而且大量使用std::move,在使用的時候有不少限制,一不當心還會出現內存訪問衝突。 所以我封裝了它,提供了一個容易操做的Rjson代理類。python

數據庫通用接口

應用類直接操做這個通用接口,實現與底層實現數據庫的分離。該接口提供了CURD標準訪問,以及批量插入和事務操做,基本能知足平時百分之九十以上的數據庫操做。
class Idb
  {
  public:
    virtual Rjson select(string tablename, Rjson& params, vector<string> fields = vector<string>(), int queryType = 1) = 0;
    virtual Rjson create(string tablename, Rjson& params) = 0;
    virtual Rjson update(string tablename, Rjson& params) = 0;
    virtual Rjson remove(string tablename, Rjson& params) = 0;
    virtual Rjson querySql(string sql, Rjson& params = Rjson(), vector<string> filelds = vector<string>()) = 0;
    virtual Rjson execSql(string sql) = 0;
    virtual Rjson insertBatch(string tablename, vector<Rjson> elements) = 0;
    virtual Rjson transGo(vector<string> sqls, bool isAsync = false) = 0;
  };

底層數據庫訪問實現

如今已經實現了sqlit3與mysql的全部功能,postgres與oracle也作了技術準備,應該在不久的未來會實現(取決因而否有時間),mssql除非有特別的需求,短時間內不會去寫。
我選擇的技術實現方式,基本上是最底層高效的方式。sqlit3 - sqllit3.h(官方的標準c接口);mysql - c api (MySQL Connector C 6.1);postgres - pqxx;oracle - occi;mssql - ?mysql

智能查詢方式設計

查詢保留字:page, size, sort, fuzzy, lks, ins, ors, count, sum, group
  • page, size, sort, 分頁排序
    在sqlit3與mysql中這比較好實現,limit來分頁是很方便的,排序只需將參數直接拼接到order by後就行了。
    查詢示例:c++

    Rjson p;
    p.AddValueInt("page", 1);
    p.AddValueInt("size", 10);
    p.AddValueString("size", "sort desc");
    (new BaseDb(...))->select("users", p);
    
    生成sql:   SELECT * FROM users  ORDER BY age desc LIMIT 0,10
  • fuzzy, 模糊查詢切換參數,不提供時爲精確匹配
    提供字段查詢的精確匹配與模糊匹配的切換。git

    Rjson p;
    p.AddValueString("username", "john");
    p.AddValueString("password", "123");
    p.AddValueString("fuzzy", "1");
    (new BaseDb(...))->select("users", p);
    
    生成sql:   SELECT * FROM users  WHERE username like '%john%'  and password like '%123%'
  • ins, lks, ors
    這是最重要的三種查詢方式,如何找出它們之間的共同點,減小冗餘代碼是關鍵。github

    • ins, 數據庫表單字段in查詢,一字段對多個值,例:算法

      查詢示例:
      Rjson p;
      p.AddValueString("ins", "age,11,22,36");
      (new BaseDb(...))->select("users", p);
      
      生成sql:   SELECT * FROM users  WHERE age in ( 11,22,26 )
    • ors, 數據庫表多字段精確查詢,or鏈接,多個字段對多個值,例:sql

      查詢示例:
      Rjson p;
      p.AddValueString("ors", "age,11,age,36");
      (new BaseDb(...))->select("users", p);
      
      生成sql:   SELECT * FROM users  WHERE  ( age = 11  or age = 26 )
    • lks, 數據庫表多字段模糊查詢,or鏈接,多個字段對多個值,例:數據庫

      查詢示例:
      Rjson p;
      p.AddValueString("lks", "username,john,password,123");
      (new BaseDb(...))->select("users", p);
      
      生成sql:   SELECT * FROM users  WHERE  ( username like '%john%'  or password like '%123%'  )
  • count, sum
    這兩個統計求和,處理方式也相似,查詢時通常要配合group與fields使用。

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

      查詢示例:
      Rjson p;
      p.AddValueString("count", "1,total");
      (new BaseDb(...))->select("users", p);
      
      生成sql:   SELECT *,count(1) as total  FROM users
    • sum, 數據庫查詢函數sum,字段求和,例:

      查詢示例:
      Rjson p;
      p.AddValueString("sum", "age,ageSum");
      (new BaseDb(...))->select("users", p);
      
      生成sql:   SELECT username,sum(age) as ageSum  FROM users
  • group, 數據庫分組函數group,例:
    查詢示例:

    Rjson p;
    p.AddValueString("group", "age");
    (new BaseDb(...))->select("users", p);
    
    生成sql:   SELECT * FROM users  GROUP BY age
不等操做符查詢支持

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

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

    Rjson p;
    p.AddValueString("age", ">,10");
    (new BaseDb(...))->select("users", p);
    
    生成sql:   SELECT * FROM users  WHERE age> 10
  • 一個字段二個操做,示例:
    查詢示例:

    Rjson p;
    p.AddValueString("age", ">=,10,<=,33");
    (new BaseDb(...))->select("users", p);
    
    生成sql:   SELECT * FROM users  WHERE age>= 10 and age<= 33
  • 使用"="去除字段的search影響,示例:
    查詢示例:

    Rjson p;
    p.AddValueString("age", "=,18");
    p.AddValueString("username", "john");
    p.AddValueString("fuzzy", "1");
    (new BaseDb(...))->select("users", p);
    
    生成sql:   SELECT * FROM users  WHERE age= 18  and username like '%john%'

系列文章規劃

  • c++操做關係數據庫通用接口設計(JSON-ORM c++版)
  • Rjson -- rapidjson代理的設計與實現
  • sqlit3 數據庫操做的實現與解析
  • mysql 數據庫操做的實現與解析
  • postgres 數據庫操做的實現與解析
  • oracle 數據庫操做的實現與解析
  • mssql 數據庫操做的實現與解析
  • 總結(若是須要的話)

項目地址

https://github.com/zhoutk/Jorm

感覺

多年沒寫C++了,恢復了一段時間,瞭解了新的C++標準,感受世界變化真快。回顧這些年,我選擇學習技術比較前衛,這些年主作node.js(Typescript),偶爾寫python, go。已經習慣了動態語言,函數式編程。忽然迴歸C++,發現好多普通的想法,實現起來還真麻煩。這就是人們的選擇吧,有得就有失。想當年我是瘋狂的迷戀C、C++,所以它們不限制我選擇編程範式。這些年,隨着硬件技術的發展,軟件業的思惟也日新月異,通常狀況下再也不爲內存,算法效率而憂心,咱們更注重開發效率和程序代碼的人性化。回到C++的懷抱,看着我半牆的C++書箱,熟悉新c++標準,我選定了主攻方向,模板、函數式編程......

相關文章
相關標籤/搜索