C++設計與實現(xiàn)ORM系統(tǒng)實例詳解
介紹
我們通用的ORM,基本模式都是想要脫離數(shù)據(jù)庫的,幾乎都在編程語言層面建立模型,由程序去與數(shù)據(jù)庫打交道。雖然脫離了數(shù)據(jù)庫的具體操作,但我們要建立各種模型文檔,用代碼去寫表之間的關系等等操作,讓初學者一時如墜云霧。我的想法是,將關系數(shù)據(jù)庫擁有的完善設計工具之優(yōu)勢,來實現(xiàn)數(shù)據(jù)設計以提供結構信息,讓json對象自動映射成為標準的SQL查詢語句。只要我們理解了標準的SQL語言,我們就能夠完成數(shù)據(jù)庫查詢操作。
依賴關系
本項目依賴 本人的 另一個項目 Zjson,此項目提供簡潔、方便、高效的Json庫。該庫使用方便,是一個單文件庫,只需要下載并引入項目即可。具體信息請移步 gitee-Zjson 或 github-Zjson 。
設計思路
ZORM 數(shù)據(jù)傳遞采用json來實現(xiàn),使數(shù)據(jù)標準能從最前端到最后端達到和諧統(tǒng)一。此項目目標,不但在要C++中使用,還要作為動態(tài)鏈接庫與node.js結合用使用,因此希望能像javascript一樣,簡潔方便的操作json。所以先行建立了zjson庫,作為此項目的先行項目。設計了數(shù)據(jù)庫通用操作接口,實現(xiàn)與底層實現(xiàn)數(shù)據(jù)庫的分離。該接口提供了CURD標準訪問,以及批量插入和事務操作,基本能滿足平時百分之九十以上的數(shù)據(jù)庫操作。項目基本目標,支持Sqlite3,Mysql,Postges三種關系數(shù)據(jù)庫,同時支持windows、linux和macOS。
項目進度
現(xiàn)在已經實現(xiàn)了sqlit3與mysql的所有功能,postgres也做了技術準備。
我選擇的技術實現(xiàn)方式,基本上是最底層高效的方式。sqlit3 - sqllit3.h(官方的標準c接口);mysql - c api (MySQL Connector C 6.1);postgres - pqxx 。
任務列表:
數(shù)據(jù)庫通用接口
應用類直接操作這個通用接口,實現(xiàn)與底層實現(xiàn)數(shù)據(jù)庫的分離。該接口提供了CURD標準訪問,以及批量插入和事務操作,基本能滿足平時百分之九十以上的數(shù)據(jù)庫操作。
class ZORM_API Idb { public: virtual Json select(string tablename, Json& params, vector<string> fields = vector<string>(), Json values = Json(JsonType::Array)) = 0; virtual Json create(string tablename, Json& params) = 0; virtual Json update(string tablename, Json& params) = 0; virtual Json remove(string tablename, Json& params) = 0; virtual Json querySql(string sql, Json params = Json(), Json values = Json(JsonType::Array), vector<string> fields = vector<string>()) = 0; virtual Json execSql(string sql, Json params = Json(), Json values = Json(JsonType::Array)) = 0; virtual Json insertBatch(string tablename, Json& elements, string constraint = "id") = 0; virtual Json transGo(Json& sqls, bool isAsync = false) = 0; };
實例構造
全局查詢開關變量:
- DbLogClose : sql 查詢語句顯示開關
- parameterized : 是否使用參數(shù)化查詢
Sqlite3:
Json options; options.addSubitem("connString", "./db.db"); //數(shù)據(jù)庫位置 options.addSubitem("DbLogClose", false); //顯示查詢語句 options.addSubitem("parameterized", false); //不使用參數(shù)化查詢 DbBase* db = new DbBase("sqlite3", options);
Mysql:
Json options; options.addSubitem("db_host", "192.168.6.6"); //mysql服務IP options.addSubitem("db_port", 3306); //端口 options.addSubitem("db_name", "dbtest"); //數(shù)據(jù)庫名稱 options.addSubitem("db_user", "root"); //登記用戶名 options.addSubitem("db_pass", "123456"); //密碼 options.addSubitem("db_char", "utf8mb4"); //連接字符設定[可選] options.addSubitem("db_conn", 5); //連接池配置[可選],默認為2 options.addSubitem("DbLogClose", true); //不顯示查詢語句 options.addSubitem("parameterized", true); //使用參數(shù)化查詢 DbBase* db = new DbBase("mysql", options);
智能查詢方式設計
查詢保留字:page, size, sort, fuzzy, lks, ins, ors, count, sum, group
page, size, sort, 分頁排序 在sqlit3與mysql中這比較好實現(xiàn),limit來分頁是很方便的,排序只需將參數(shù)直接拼接到order by后就好了。
查詢示例:
Json p; p.addSubitem("page", 1); p.addSubitem("size", 10); p.addSubitem("size", "sort desc"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users ORDER BY age desc LIMIT 0,10
fuzzy, 模糊查詢切換參數(shù),不提供時為精確匹配 提供字段查詢的精確匹配與模糊匹配的切換。
Json p; p.addSubitem("username", "john"); p.addSubitem("password", "123"); p.addSubitem("fuzzy", 1); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE username like '%john%' and password like '%123%'
ins, lks, ors 這是最重要的三種查詢方式,如何找出它們之間的共同點,減少冗余代碼是關鍵。
Json p; p.addSubitem("ins", "age,11,22,36"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE age in ( 11,22,26 )
Json p; p.addSubitem("ors", "age,11,age,36"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE ( age = 11 or age = 26 )
Json p; p.addSubitem("lks", "username,john,password,123"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE ( username like '%john%' or password like '%123%' )
- ins, 數(shù)據(jù)庫表單字段in查詢,一字段對多個值,例:
查詢示例: - ors, 數(shù)據(jù)庫表多字段精確查詢,or連接,多個字段對多個值,例:
查詢示例: - lks, 數(shù)據(jù)庫表多字段模糊查詢,or連接,多個字段對多個值,例: 查詢示例:
count, sum 這兩個統(tǒng)計求和,處理方式也類似,查詢時一般要配合group與fields使用。
Json p; p.addSubitem("count", "1,total"); (new DbBase(...))->select("users", p); 生成sql: SELECT *,count(1) as total FROM users
Json p; p.addSubitem("sum", "age,ageSum"); (new DbBase(...))->select("users", p); 生成sql: SELECT username,sum(age) as ageSum FROM users
- count, 數(shù)據(jù)庫查詢函數(shù)count,行統(tǒng)計,例: 查詢示例:
- sum, 數(shù)據(jù)庫查詢函數(shù)sum,字段求和,例: 查詢示例:
group, 數(shù)據(jù)庫分組函數(shù)group,例:
查詢示例:
Json p; p.addSubitem("group", "age"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users GROUP BY age
不等操作符查詢支持
支持的不等操作符有:>, >=, <, <=, <>, =;逗號符為分隔符,一個字段支持一或二個操作。
特殊處:使用"="可以使某個字段跳過search影響,讓模糊匹配與精確匹配同時出現(xiàn)在一個查詢語句中
一個字段一個操作,示例: 查詢示例:
Json p; p.addSubitem("age", ">,10"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE age> 10
一個字段二個操作,示例: 查詢示例:
Json p; p.addSubitem("age", ">=,10,<=,33"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE age>= 10 and age<= 33
使用"="去除字段的fuzzy影響,示例: 查詢示例:
Json p; p.addSubitem("age", "=,18"); p.addSubitem("username", "john"); p.addSubitem("fuzzy", "1"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE age= 18 and username like '%john%'
具體使用方法,請參看uint test。
單元測試
有完整功能的單元測試用例,請參見tests目錄下的測試用例。
測試用例運行結果樣例
項目地址
https://github.com/zhoutk/zorm
運行方法
該項目在vs2019, gcc7.5, clang12.0下均編譯運行正常。
git clone https://github.com/zhoutk/zorm cd zorm cmake -Bbuild . ---windows cd build && cmake --build . ---linux & macos cd build && make run zorm or ctest
注在linux下需要先行安裝mysql開發(fā)庫, 并先手動建立數(shù)據(jù)庫 dbtest。
在ubuntu下的命令是: apt install libmysqlclient-dev
相關項目
會有一系列項目出爐,網絡服務相關,敬請期待...
以上就是C++設計與實現(xiàn)ORM系統(tǒng)實例詳解的詳細內容,更多關于C++ ORM系統(tǒng)的資料請關注腳本之家其它相關文章!
相關文章
Qt連接數(shù)據(jù)庫并實現(xiàn)增刪改查操作
這篇文章主要為大家詳細介紹了Qt如何連接數(shù)據(jù)庫并實現(xiàn)增刪改查等基本操作,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-09-09C++ 多線程編程建議之 C++ 對多線程/并發(fā)的支持(下)
這篇文章主要介紹的是 C++ 多線程編程建議之 C++ 對多線程/并發(fā)的支持的相關資料,承接前文 現(xiàn)代 C++ 對多線程/并發(fā)的支持,接下來我們看看回發(fā)生什么吧2021-10-10Qt動態(tài)庫調用宿主進程中的對象方法純虛函數(shù)使用
這篇文章主要為大家介紹了Qt動態(tài)庫調用宿主進程中的對象方法純虛函數(shù)使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08