暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

GitHub 开源推荐:适用于C++/QT的SQLite ORM 框架

猿武场 2022-03-07
8122

「 GitHub 开源推荐 」关注优秀开源项目

  整理 | 猿胖子

  出品 | 猿武场(ID:apesarena)

关注公众号并回复数字「 1024 」加入猿武场微信社群 

” Hello,World !“  大家好,终于到了本期的 GitHub 开源项目推荐
这次给大家介绍的是一个适用于C++/Qt 的 SQLite ORM 框架,这个框架呢还是非常优秀的,具体有多强大呢?我们详细来聊一聊

SQLite ORM 特性介绍

其最大的优点是不需要其他依赖(唯一的依赖:libsqlite3),仅包含自身 library 和头文件即可,其他一些特性:

  • 使用语法直观,支持增删改查外对UNION、EXCEPT和INTERSECT的支持也比较好

  • 兼容 STL ,支持自定义类型绑定

  • 具备序列化和反序列化

  • 支持 ORDER BY 和 LIMIT、OFFSET 以及 GROUP BY DISTINCT

  • 具有 C++ 标准代码风格

  • 支持 SQLite 内存模式

// github 项目地址

https://github.com/fnc12/sqlite_orm



快速创建简单数据模型到数据库的映射

主要体现在有主键和没有主键的(CRUD)对象,并且可以显式指定表名和列名(无需与类的实际命名一致),看一个例子:


struct User{
    int id;
    std::string firstName;
    std::string lastName;
    int birthDate;
    std::unique_ptr<std::string> imageUrl;
    int typeId;
};

struct UserType {
    int id;
    std::string name;
};


我们一般的数据库创建语句这样写,比如:


// create sql

CREATE TABLE users (id integer primary key autoincrement, first_name text not null, last_name text not null, birth_date integer not null, image_url text, type_id integer not null)

CREATE TABLE user_types (id integer primary key autoincrement, name text not null DEFAULT 'name_placeholder')


那么现在采用ORM  就可以这样创建,如下:


 1// start
2
3using namespace sqlite_orm;
4auto storage = make_storage("db.sqlite",
5                            make_table("users",
6                                       make_column("id", &User::id, autoincrement(), primary_key()),
7                                       make_column("first_name", &User::firstName),
8                                       make_column("last_name", &User::lastName),
9                                       make_column("birth_date", &User::birthDate),
10                                       make_column("image_url", &User::imageUrl),
11                                       make_column("type_id", &User::typeId)),
12                            make_table("user_types",
13                                       make_column("id", &UserType::id, autoincrement(), primary_key()),
14                                       make_column("name", &UserType::name, default_value("name_placeholder"))));


是不是容易很多,更方便呢?我们完全可以不必在显式指定映射类型,默认会从创建过程中传递的成员指针推导出来( 例如:&User::id )

要创建一个列就至少传递两个参数:在表中的名称 和映射的类成员指针 

CRUD 

我们创建个 User 并将其插入到 User 表中


 1// user 对象
2User user{-1"Jonh""Doe"664416000
3          std::make_unique<std::string>("url_to_heaven"), 3 };
4
5//执行插入操作
6
7auto insertedId = storage.insert(user);  
8//  insertedId = 8
9cout << "insertedId = " << insertedId << endl;    
10user.id = insertedId;
11
12User secondUser{-1"Alice""Inwonder"831168000, {} , 2};
13insertedId = storage.insert(secondUser);
14secondUser.id = insertedId;


接下来通过 ID 获取用户信息


 1// get user by id.
2try{
3    auto user = storage.get<User>(insertedId);
4    cout << "user = " << user.firstName << " " 
5         << user.lastName << endl;
6}catch(std::system_error e) {
7    cout << e.what() << endl;
8}catch(...){
9    cout << "unknown exeption" << endl;
10}


当然,不用异常处理也可以的


1// get user by id.
2
3if ( auto user = storage.get_pointer<User>(insertedId)){ 
4    cout << " user = " << user-> firstName << "  " 
5         << user-> lastName << endl
6else { 
7    cout << " no id " << insertedId << endl
8}


更新操作,我们可以通调用 update 更新用户信息


1// 更新用户信息
2user.firstName = "尼古拉斯 赵四" ; 
3user.imageUrl = " ./xcaq/20220305151.png " 
4storage.update(user);


删除也一样的,只需要传 id 就可以了


1// insertedId:user id
2storage.remove<User>(insertedId)


查询所有用户信息


 1// 使用 vector
2auto allUsers = storage.get_all<User>();
3cout << "allUsers (" << allUsers.size() << "):" << endl;
4for(auto &user : allUsers) {
5    cout << storage.dump(user) << endl
6}
7
8// 使用 vector
9auto allUsersList = storage.get_all<User, std::list<User>>();
10// STL 方式
11for(auto &user : storage.iterate<User>()) {
12    cout << storage.dump(user) << endl;
13}


聚合查询的使用


 1//  SELECT AVG(id) FROM users
2auto averageId = storage.avg(&User::id);   
3//  averageId = 4.5 
4cout << "averageId = " << averageId << endl
5
6//  SELECT AVG(birth_date) FROM users
7auto averageBirthDate = storage.avg(&User::birthDate);  
8//  averageBirthDate = 6.64416e+08
9cout << "averageBirthDate = " << averageBirthDate << endl;  
10
11
12//  SELECT COUNT(*) FROM users
13auto usersCount = storage.count<User>();   
14//  users count = 8 
15cout << "users count = " << usersCount << endl;     
16
17//  SELECT COUNT(id) FROM users
18auto countId = storage.count(&User::id); 
19//  countId = 8  
20cout << "countId = " << countId << endl;   
21
22//  SELECT COUNT(image_url) FROM users
23auto countImageUrl = storage.count(&User::imageUrl); 
24//  countImageUrl = 5  
25cout << "countImageUrl = " << countImageUrl << endl;      
26
27//  SELECT GROUP_CONCAT(id) FROM users
28auto concatedUserId = storage.group_concat(&User::id);
29//  concatedUserId = 1,2,3,4,5,6,7,8      
30cout << "concatedUserId = " << concatedUserId << endl
31
32
33//  SELECT GROUP_CONCAT(id, "---") FROM users
34auto concatedUserIdWithDashes = 
35                     storage.group_concat(&User::id, "---");    
36//  concatedUserIdWithDashes = 1---2---3---4---5---6---7---8 
37cout << "concatedUserIdWithDashes = " 
38     << concatedUserIdWithDashes << endl;     
39
40
41//  SELECT MAX(id) FROM users
42if(auto maxId = storage.max(&User::id)){    
43    //  maxId = 12 
44    cout << "maxId = " << *maxId <<endl;    
45 (maxId is std::unique_ptr<int>)
46}else{
47    cout << "maxId is null" << endl;
48}
49
50//  SELECT MAX(first_name) FROM users
51if(auto maxFirstName = storage.max(&User::firstName)){ 
52    cout << "maxFirstName = " << *maxFirstName << endl
53//  maxFirstName = Jonh (maxFirstName is std::unique_ptr<std::string>)
54}else{
55    cout << "maxFirstName is null" << endl;
56}
57
58//  SELECT TOTAL(id) FROM users
59auto totalId = storage.total(&User::id);
60//  totalId is double (always)
61cout << "totalId = " << totalId << endl;   
62
63.... 

 

用法 

克隆仓库代码,使用cmake编译,将编译好的lib引入工程文件或配置系统变量,记得加入头文件


更多特性及使用技巧可以去GitHub项目主页查看,当然你也可以点击下方关注[ 猿武场 ] 公众号回复 “ ORM ” 获取更多相关代码实例哦 ! 



版权声明:本文来自原创,版权归猿武场作者所有。如需转载,请注明出处。


注公众号并回复数字「 1024 」加入猿武场微信社群 

欢迎加入程序员社群,更多技术摘要等你拿走

社群福利:

1. 行业大牛技术手札,知识点汇总

2. 求职/招聘信息内推

4. 人际交往,增强技术宅人际交流;

5. 调节繁杂无趣的闲暇时光;

6. 不定期线上周边线下技术活动沙龙


代 / 码 / 改 / 变 / 世 / 界
感谢您对猿武场的关注与支持


文章转载自猿武场,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论