C++設(shè)計(jì)與實(shí)現(xiàn)ORM系統(tǒng)實(shí)例詳解
介紹
我們通用的ORM,基本模式都是想要脫離數(shù)據(jù)庫的,幾乎都在編程語言層面建立模型,由程序去與數(shù)據(jù)庫打交道。雖然脫離了數(shù)據(jù)庫的具體操作,但我們要建立各種模型文檔,用代碼去寫表之間的關(guān)系等等操作,讓初學(xué)者一時(shí)如墜云霧。我的想法是,將關(guān)系數(shù)據(jù)庫擁有的完善設(shè)計(jì)工具之優(yōu)勢,來實(shí)現(xiàn)數(shù)據(jù)設(shè)計(jì)以提供結(jié)構(gòu)信息,讓json對象自動映射成為標(biāo)準(zhǔn)的SQL查詢語句。只要我們理解了標(biāo)準(zhǔn)的SQL語言,我們就能夠完成數(shù)據(jù)庫查詢操作。
依賴關(guān)系
本項(xiàng)目依賴 本人的 另一個(gè)項(xiàng)目 Zjson,此項(xiàng)目提供簡潔、方便、高效的Json庫。該庫使用方便,是一個(gè)單文件庫,只需要下載并引入項(xiàng)目即可。具體信息請移步 gitee-Zjson 或 github-Zjson 。
設(shè)計(jì)思路
ZORM 數(shù)據(jù)傳遞采用json來實(shí)現(xiàn),使數(shù)據(jù)標(biāo)準(zhǔn)能從最前端到最后端達(dá)到和諧統(tǒng)一。此項(xiàng)目目標(biāo),不但在要C++中使用,還要作為動態(tài)鏈接庫與node.js結(jié)合用使用,因此希望能像javascript一樣,簡潔方便的操作json。所以先行建立了zjson庫,作為此項(xiàng)目的先行項(xiàng)目。設(shè)計(jì)了數(shù)據(jù)庫通用操作接口,實(shí)現(xiàn)與底層實(shí)現(xiàn)數(shù)據(jù)庫的分離。該接口提供了CURD標(biāo)準(zhǔn)訪問,以及批量插入和事務(wù)操作,基本能滿足平時(shí)百分之九十以上的數(shù)據(jù)庫操作。項(xiàng)目基本目標(biāo),支持Sqlite3,Mysql,Postges三種關(guān)系數(shù)據(jù)庫,同時(shí)支持windows、linux和macOS。
項(xiàng)目進(jìn)度
現(xiàn)在已經(jīng)實(shí)現(xiàn)了sqlit3與mysql的所有功能,postgres也做了技術(shù)準(zhǔn)備。
我選擇的技術(shù)實(shí)現(xiàn)方式,基本上是最底層高效的方式。sqlit3 - sqllit3.h(官方的標(biāo)準(zhǔn)c接口);mysql - c api (MySQL Connector C 6.1);postgres - pqxx 。
任務(wù)列表:
數(shù)據(jù)庫通用接口
應(yīng)用類直接操作這個(gè)通用接口,實(shí)現(xiàn)與底層實(shí)現(xiàn)數(shù)據(jù)庫的分離。該接口提供了CURD標(biāo)準(zhǔn)訪問,以及批量插入和事務(wù)操作,基本能滿足平時(shí)百分之九十以上的數(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; };
實(shí)例構(gòu)造
全局查詢開關(guān)變量:
- DbLogClose : sql 查詢語句顯示開關(guān)
- 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服務(wù)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"); //連接字符設(shè)定[可選] options.addSubitem("db_conn", 5); //連接池配置[可選],默認(rèn)為2 options.addSubitem("DbLogClose", true); //不顯示查詢語句 options.addSubitem("parameterized", true); //使用參數(shù)化查詢 DbBase* db = new DbBase("mysql", options);
智能查詢方式設(shè)計(jì)
查詢保留字:page, size, sort, fuzzy, lks, ins, ors, count, sum, group
page, size, sort, 分頁排序 在sqlit3與mysql中這比較好實(shí)現(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ù),不提供時(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 這是最重要的三種查詢方式,如何找出它們之間的共同點(diǎn),減少冗余代碼是關(guān)鍵。
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查詢,一字段對多個(gè)值,例:
查詢示例: - ors, 數(shù)據(jù)庫表多字段精確查詢,or連接,多個(gè)字段對多個(gè)值,例:
查詢示例: - lks, 數(shù)據(jù)庫表多字段模糊查詢,or連接,多個(gè)字段對多個(gè)值,例: 查詢示例:
count, sum 這兩個(gè)統(tǒng)計(jì)求和,處理方式也類似,查詢時(shí)一般要配合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)計(jì),例: 查詢示例:
- 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
不等操作符查詢支持
支持的不等操作符有:>, >=, <, <=, <>, =;逗號符為分隔符,一個(gè)字段支持一或二個(gè)操作。
特殊處:使用"="可以使某個(gè)字段跳過search影響,讓模糊匹配與精確匹配同時(shí)出現(xiàn)在一個(gè)查詢語句中
一個(gè)字段一個(gè)操作,示例: 查詢示例:
Json p; p.addSubitem("age", ">,10"); (new DbBase(...))->select("users", p); 生成sql: SELECT * FROM users WHERE age> 10
一個(gè)字段二個(gè)操作,示例: 查詢示例:
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目錄下的測試用例。
測試用例運(yùn)行結(jié)果樣例
項(xiàng)目地址
https://github.com/zhoutk/zorm
運(yùn)行方法
該項(xiàng)目在vs2019, gcc7.5, clang12.0下均編譯運(yùn)行正常。
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
相關(guān)項(xiàng)目
會有一系列項(xiàng)目出爐,網(wǎng)絡(luò)服務(wù)相關(guān),敬請期待...
以上就是C++設(shè)計(jì)與實(shí)現(xiàn)ORM系統(tǒng)實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ ORM系統(tǒng)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Qt連接數(shù)據(jù)庫并實(shí)現(xiàn)增刪改查操作
這篇文章主要為大家詳細(xì)介紹了Qt如何連接數(shù)據(jù)庫并實(shí)現(xiàn)增刪改查等基本操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09C++ 多線程編程建議之 C++ 對多線程/并發(fā)的支持(下)
這篇文章主要介紹的是 C++ 多線程編程建議之 C++ 對多線程/并發(fā)的支持的相關(guān)資料,承接前文 現(xiàn)代 C++ 對多線程/并發(fā)的支持,接下來我們看看回發(fā)生什么吧2021-10-10C++實(shí)現(xiàn)班級成績管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)班級成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02C++中實(shí)現(xiàn)矩陣的加法和乘法實(shí)例
這篇文章主要介紹了C++中實(shí)現(xiàn)矩陣的加法和乘法實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03Qt動態(tài)庫調(diào)用宿主進(jìn)程中的對象方法純虛函數(shù)使用
這篇文章主要為大家介紹了Qt動態(tài)庫調(diào)用宿主進(jìn)程中的對象方法純虛函數(shù)使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08