当前位置: 首页 > ds >正文

【C++组件】ODB 安装与使用

🌈 个人主页:Zfox_
🔥 系列专栏:C++框架/库

目录

  • 🔥 ODB2.5 版本安装
    • 🦋 安装 build2:
    • 🦋 安装 odb-compiler
    • 🦋 安装 ODB 运行时库
    • 🦋 安装 mysql 和客户端开发包
    • 🦋 安装 boost profile 库
    • 🦋 测试样例:
  • 🔥 ODB 常见操作介绍
    • 🦋 ODB 类型映射
  • 🔥 ODB 编程
    • 🦋 操作类与接口介绍
    • 🦋 使用样例
      • 🎀 官网链接
  • 🔥 共勉

🔥 ODB2.5 版本安装

ODB 框架:数据库 ORM 框架

什么是ORM?

  • 对象关系映射(Object Relational Mapping,简称ORM)用于在面向对象的编程语言和关系型数据库之间进行数据转换。它允许开发者使用对象的方式来操作数据库,而不需要直接编写 SQL 语句。ORM 的主要目的是简化数据库操作,提高开发效率,同时减少错误。

🦋 安装 build2:

因为 build2 安装时,有可能会版本更新,从 16 变成 17,或从 17 变 18,因此注意,先从 build2 官网查看安装步骤…

安装步骤: https://build2.org/install.xhtml#unix

$ curl -sSfO https://download.build2.org/0.17.0/build2-install-0.17.0.sh$ shasum -a 256 -b build2-install-0.17.0.shb84e4114c61aa94c3f6278f010a0dc0536dda65ac39d3863152ec9b64510b86e$ sh build2-install-0.17.0.sh

安装中因为网络问题,超时失败,解决:将超时时间设置的更长一些

$ sh build2-install-0.17.0.sh --timeout 1800

🦋 安装 odb-compiler

dev@dev-host:~/workspace$ #注意这里的 gcc-11 需要根据你自己版本而定
dev@dev-host:~/workspace$ sudo apt-get install gcc-11-plugin-dev
dev@dev-host:~/workspace$ mkdir odb-build && cd odb-build
dev@dev-host:~/workspace/odb-build$ bpkg create -d odb-gcc-N cc\
config.cxx=g++ \
config.cc.coptions=-O3 \
config.bin.rpath=/usr/lib \
config.install.root=/usr/ \
config.install.sudo=sudo
dev@dev-host:~/workspace/odb-build$ cd odb-gcc-N
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ bpkg build odb@https://pkg.cppget.org/1/beta
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ bpkg test odb test 
odb-2.5.0-b.25+1/tests/testscript{testscript}
tested odb/2.5.0-b.25+1
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ bpkg install odb
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ odb --version
bash: /usr/bin/odb: No such file or directory
#如果报错了,找不到 odb,那就在执行下边的命令
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ sudo echo 'export
PATH=${PATH}:/usr/local/bin' >> ~/.bashrc
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ export
PATH=${PATH}:/usr/local/bin
dev@dev-host:~/workspace/odb-build/odb-gcc-N$ odb --version
ODB object-relational mapping (ORM) compiler for C++ 2.5.0-b.25
Copyright (c) 2009-2023 Code Synthesis Tools CC.
This is free software; see the source for copying conditions.There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

🦋 安装 ODB 运行时库

dev@dev-host:~/workspace/odb-build/odb-gcc-N$ cd ..
dev@dev-host:~/workspace/odb-build$ bpkg create -d libodb-gcc-N cc\
config.cxx=g++ \
config.cc.coptions=-O3 \
config.install.root=/usr/ \
config.install.sudo=sudo
dev@dev-host:~/workspace/odb-build$ cd libodb-gcc-N
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg add https://pkg.cppget.org/1/beta
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg fetch
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg build libodb
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg build libodb-mysql

🦋 安装 mysql 和客户端开发包

sudo apt install mysql-server
sudo apt install -y libmysqlclient-dev

配置 mysql

sudo vim /etc/my.cnf 或者 /etc/mysql/my.cnf 有哪个修改哪个就行
#添加以下内容
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character-set-server=utf8
bind-address = 0.0.0.0

重启 mysql,并设置开机启动

sudo systemctl restart mysql
sudo systemctl enable mysql

🦋 安装 boost profile 库

dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg build libodb-boost

总体打包安装:

dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg install --all --recursive

总体卸载:

dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg uninstall --all --recursive

总体升级:

dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg fetch
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg status
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg uninstall --all --recursive
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg build --upgrade --recursive
dev@dev-host:~/workspace/odb-build/libodb-gcc-N$ bpkg install --all --recursive

🦋 测试样例:

编写数据结构文件: person.hxx

#pragma once
#include <string>
#include <cstddef> // std::size_t
#include <boost/date_time/posix_time/posix_time.hpp>
/*
在 C++ 中,要使用 ODB 将类声明为持久化类,需要包含 ODB 的核心头文
件,并使用 #pragma db object 指令
#pragma db object 指示 ODB 编译器将 person 类视为一个持久化类。
*/
#include <odb/core.hxx>
typedef boost::posix_time::ptime ptime;
#pragma db object
class Person
{
public:Person(const std::string &name, int age, const ptime &update) : _name(name), _age(age), _update(update) {}void age(int val) { _age = val; }int age() { return _age; }void name(const std::string &val) { _name = val; }std::string name() { return _name; }void update(const ptime &update) { _update = update; }std::string update() { return boost::posix_time::to_simple_string(_update); }private:// 将 odb:: access 类作为 person 类的朋友。// 这是使数据库支持代码可访问默认构造函数和数据成员所必需的。// 如果类具有公共默认构造函数和公共数据成员或数据成员的公共访问器和修饰符,则不需要友元声明friend class odb::access;Person() {}//_id 成员前面的 pragma 告诉 ODB 编译器,以下成员是对象的标识符。 auto 说明符指示它是数据库分配的 ID。
#pragma db id auto // 表示 ID 字段将自动生成(通常是数据库中的主键)。unsigned long _id;unsigned short _age;std::string _name;
#pragma db type("TIMESTAMP") not_nullboost::posix_time::ptime _update;
};// 将 ODB 编译指示组合在一起,并放在类定义之后。它们也可以移动到一个单独的标头中,使原始类完全保持不变
// #pragma db object(person)
// #pragma db member(person::_name) id
// 完成后,需要使用 odb 编译器将当前所写的代码生成数据库支持代码
// odb -d mysql --generate-query --generate-schema person.hxx
// 如果用到了 boost 库中的接口,则需要使用选项 : --profile boost/datetime
// odb -d mysql --generate-query --generate-schema --profile boost/date - time person.hxx

生成数据库支持的代码文件:

$ odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time person.hxx
$ ls
person-odb.cxx person-odb.hxx person-odb.ixx person.hxx person.sql

编写主函数代码: main.cc

#include <string>
#include <memory>  // std::auto_ptr
#include <cstdlib> // std::exit
#include <iostream>
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>#include "person.hxx"
#include "person-odb.hxx"
int main()
{std::shared_ptr<odb::core::database> db(new odb::mysql::database("root", "502502", "TestDB", "127.0.0.1", 0, 0, "utf8"));if (!db){return -1;}ptime p = boost::posix_time::second_clock::local_time();Person zhang("小张", 18, p);Person wang("小王", 19, p);typedef odb::query<Person> query;typedef odb::result<Person> result;{odb::core::transaction t(db->begin());size_t zid = db->persist(zhang);size_t wid = db->persist(wang);t.commit();}{odb::core::transaction t(db->begin());result r(db->query<Person>());for (result::iterator i(r.begin()); i != r.end(); ++i){std::cout << "Hello, " << i->name() << " ";std::cout << i->age() << " " << i->update() << std::endl;}t.commit();}return 0;
}
c++ -o test test.cpp personodb.cxx -lodb-mysql -lodb -lodb-boost

🔥 ODB 常见操作介绍

🦋 ODB 类型映射

在这里插入图片描述
在这里插入图片描述

🔥 ODB 编程

ODB(Open Database)在数据元结构定义时,使用预处理器指令(#pragma)来提供元数据,这些元数据指示如何将 C++类型映射到数据库模式。这些 #pragma 指令是在 C++代码中使用的,它们不是 C++语言的一部分,而是特定于 ODB 编译器的扩展。(为 C++ 中的类和成员指定数据库的属性)

以下是 ODB 中常用的一些 #pragma 指令:

  1. #pragma db object:
    • 用于声明一个类是数据库对象,即这个类将映射到数据库中的一个表。
  2. #pragma db table(“table_name”):
    • 指定类映射到数据库中的表名。如果不指定,则默认使用类名。
  3. #pragma db id:
    • 标记类中的一个成员变量作为数据库表的主键。
  4. #pragma db column(“column_name”):
    • 指定类成员映射到数据库表中的列名。如果不指定,则默认使用成员变量的名字。
  5. #pragma db view:
    • 用于声明一个类是一个数据库视图,而不是一个表。
  6. #pragma db session:
    • 用于声明一个全局或成员变量是数据库会话。
  7. #pragma db query(“query”):
    • 用于定义自定义的查询函数
  8. #pragma db index(“index_name”):
    • 指定成员变量应该被索引
  9. #pragma db default(“default_value”):
    • 指定成员变量的默认值
  10. #pragma db unique:
    • 指定成员变量或一组变量应该具有唯一性约束
  11. #pragma db not_null:(默认)
    • 指定成员变量不允许为空
  12. #pragma db auto:
    • 指定成员变量的值在插入时自动生成(例如,自动递增的主键
  13. #pragma db transient:
    • 指定成员变量不应该被持久化到数据库中。
  14. #pragma db type(“type_name”):
    • 指定成员变量的数据库类型
  15. #pragma db convert(“converter”):
    • 指定用于成员变量的自定义类型转换器
  16. #pragma db pool(“pool_name”):
    • 指定用于数据库连接的连接池。
  17. #pragma db trigger(“trigger_name”):
    • 指定在插入、更新或删除操作时触发的触发器

预处理指定基本使用

#pragma once
#include <string>class Student {private:unsigned long _id;std::string _sn;std::string _name;unsigned short _age;unsigned long _classes_id;
};class Classes {private :unsigned long _id;std::string _name;
};// 查询所有的学生信息,并显示班级名称    view 声明一个视图 并将其与一个类关联起来,通常用于复杂查询
#pragma db view object(Student)\object(Classes classes : Student._classes_id == Classes._id)\query((?))
struct classes_student {#pragma db column(Student::_id)unsigned long _id;#pragma db column(Student::_sn)std::string _sn;#pragma db column(Student::_name)std::string _name;#pragma db column(Student::_age)unsigned short _age;#pragma db column(Classes::_name)unsigned long _classes_name;
};// 只查询学生姓名  ,   (?)  外部调用时传入的过滤条件
#pragma db view query("select name from Student" + (?))
struct all_name {std::string name;
};//odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time student.hxx

🦋 操作类与接口介绍

namespace odb
{namespace mysql{// mysql 连接池对象类class LIBODB_MYSQL_EXPORT new_connection_factory : public connection_pool_factory{connection_pool_factory(std::size_t max_connections = 0,std::size_t min_connections = 0,bool ping = true);};}// 操作句柄类class LIBODB_EXPORT database{// 新增数据persist(T &object);// 更新数据void update(T &object);void erase(T &object);  unsigned long long erase_query(const std::string &);unsigned long long erase_query(const odb::query<T> &);result<T> query(const std::string &);result<T> query(const odb::query<T> &, bool cache = true);typename result<T>::pointer_type query_one(const odb::query<T> &);virtual transaction_impl *begin() = 0;};// 事务操作类class LIBODB_EXPORT transaction{transaction(transaction_impl *, bool make_current = true);void commit();void rollback();};// 针对可能为空的字段封装的类似于智能指针的类型template <typename T>class nullable{typedef T value_type;T &get();const T &get() const;T *operator->();const T *operator->() const;T &operator*();const T &operator*() const;};// 针对查询结果所封装的容器类template <typename T>class result : result_base<T, class_traits<T>::kind>{result();result(const result &r);iterator begin();iterator end();size_type size() bool empty();};// 针对查询封装的条件类class LIBODB_EXPORT query_base{explicit query_base(const std::string &native);const clause_type &clause();};namespace mysql{template <typename T>class query : public query_base,public query_selector<T, id_mysql>::columns_type{query(const std::string &q);query(const query_base &q);query(bool v);}};template <typename T>class query<T, mysql::query_base> : public mysql::query<T>{query(bool v);query(const std::string &q);query(const mysql::query_base &q);};
}

🦋 使用样例

在 odb 的使用中,我们最关注的其实是三个点,

  • 一个是增删改的基础操作
  • 一个是基于原生 sql 语句的查询
  • 一个是基于多表连接的复杂查找

能解决这三个问题,就能满足数据库的基本功能操作。

#include <string>
#include <iostream>
#include <gflags/gflags.h>
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include "student.hxx"
#include "student-odb.hxx"DEFINE_string(host, "127.0.0.1", "这是Mysql服务器地址");
DEFINE_int32(port, 3306, "这是Mysql服务器端口");
DEFINE_string(db, "TestDB", "数据库默认库名称");
DEFINE_string(user, "root", "这是Mysql用户名");
DEFINE_string(pswd, "502502", "这是Mysql密码");
DEFINE_string(cset, "utf8", "这是Mysql客户端字符集");
DEFINE_int32(max_pool, 3, "这是Mysql连接池最大连接数量");void insert_classes(odb::mysql::database &db) {try {// 3. 获取事务对象开启事务odb::transaction trans(db.begin());// 4. 数据操作Classes c1("一年级一班");Classes c2("一年级二班");db.persist(c1);db.persist(c2);// 5. 提交事务trans.commit();} catch (std::exception &e) {std::cout << "插入班级数据出错: " << e.what() << std::endl;}
}void insert_student(odb::mysql::database &db) {try {// 3. 获取事务对象开启事务odb::transaction trans(db.begin());// 4. 数据操作Student s1(1, "张三", 18, 1);Student s2(2, "李四", 19, 1);Student s3(3, "王五", 18, 1);Student s4(4, "赵六", 15, 2);Student s5(5, "田七", 18, 2);Student s6(6, "孙八", 23, 2);db.persist(s1);db.persist(s2);db.persist(s3);db.persist(s4);db.persist(s5);db.persist(s6);// 5. 提交事务trans.commit();} catch (std::exception &e) {std::cout << "插入学生数据出错: " << e.what() << std::endl;}
}void update_student(odb::mysql::database &db, Student &stu) {try {// 3. 获取事务对象开启事务odb::transaction trans(db.begin());// 4. 数据操作db.update(stu);// 5. 提交事务trans.commit();} catch (std::exception &e) {std::cout << "更新学生数据出错: " << e.what() << std::endl;}
}Student select_student(odb::mysql::database &db) {Student res;try {// 3. 获取事务对象开启事务odb::transaction trans(db.begin());// 4. 数据操作typedef odb::query<Student> query;typedef odb::result<Student> result;result r(db.query<Student>(query::name == "张三"));      // 对应上面 typedef 的,知道是 Student 成员,知道有nameif (r.size() != 1) {std::cout << "数据量不对! \n";return Student();}res = *r.begin();// 5. 提交事务trans.commit();} catch (std::exception &e) {std::cout << "更新学生数据出错: " << e.what() << std::endl;}return res;
}void remove_student(odb::mysql::database &db) {Student res;try {// 3. 获取事务对象开启事务odb::transaction trans(db.begin());// 4. 数据操作typedef odb::query<Student> query;  // 通过这个类型才能引用内部的字段db.erase_query<Student>(query::classes_id == 2);// 5. 提交事务trans.commit();} catch (std::exception &e) {std::cout << "删除学生数据出错: " << e.what() << std::endl;}
}void classes_student(odb::mysql::database &db) {Student res;try {// 3. 获取事务对象开启事务odb::transaction trans(db.begin());// 4. 数据操作typedef odb::query<struct classes_student> query;  // 通过这个类型才能引用内部的字段typedef odb::result<struct classes_student> result;result r(db.query<struct classes_student>(query::classes::id == 1));for (auto it = r.begin(); it != r.end(); ++it) {std::cout << it->id << std::endl;std::cout << it->sn << std::endl;std::cout << it->name << std::endl;std::cout << *it->age << std::endl;std::cout << it->classes_name << std::endl;}// 5. 提交事务trans.commit();} catch (std::exception &e) {std::cout << "删除学生数据出错: " << e.what() << std::endl;}
}void all_student(odb::mysql::database &db)
{try {//获取事务对象开启事务odb::transaction trans(db.begin());typedef odb::query<Student> query;typedef odb::result<struct all_name> result;result r(db.query<struct all_name>(query::id == 1));for (auto it = r.begin(); it != r.end(); ++it) {std::cout << it->name << std::endl;}//5. 提交事务trans.commit();}catch (std::exception &e) {std::cout << "查询所有学生姓名数据出错:" << e.what() << std::endl;}
}int main(int argc, char *argv[])
{google::ParseCommandLineFlags(&argc, &argv, true);// 1. 构造连接池工厂配置对象std::unique_ptr<odb::mysql::connection_pool_factory> cpf(new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));// 2. 构造数据库操作对象odb::mysql::database db(FLAGS_user, FLAGS_pswd, FLAGS_db, FLAGS_host, FLAGS_port, "", FLAGS_cset, 0, std::move(cpf));// 3. 获取事务对象开启事务std::unique_ptr<odb::mysql::transaction_impl> trans(db.begin());// 4. 数据操作// insert_classes(db);// insert_student(db);// Student stu = select_student(db);// std::cout << stu.sn() << std::endl;// std::cout << stu.name() << std::endl;// if (stu.age()) std::cout << *stu.age() << std::endl;// std::cout << stu.classes_id() << std::endl;// stu.age(15);// update_student(db, stu);// remove_student(db);// classes_student(db);all_student(db);return 0;
}

🎀 官网链接

  • https://codesynthesis.com/products/odb/doc/manual.xhtml
  • https://codesynthesis.com/products/odb/
  • https://codesynthesis.com/products/odb/doc/install-build2.xhtml

🔥 共勉

😋 以上就是我对 【C++组件】ODB 安装与使用 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉
在这里插入图片描述

http://www.xdnf.cn/news/18852.html

相关文章:

  • 春秋云镜 TOISEC 部分WP
  • 3.1 存储系统概述 (答案见原书 P149)
  • 鸿蒙中Frame分析
  • NLP:Transformer各子模块作用(特别分享1)
  • 网络编程socket-Udp
  • 互联网大厂Java面试模拟:深度解析核心技术
  • 100个实用小工具1.3历年股价分析小工具新增股价批量下载
  • 使用UE5开发2.5D开放世界战略养成类游戏的硬件配置指南
  • 电子厂静电释放检测误报率↓81%!陌讯多模态融合算法在安全生产监控的落地实践
  • imx6ull-驱动开发篇38——Linux INPUT 子系统
  • MATLAB 数值计算进阶:微分方程求解与矩阵运算高效方法
  • 从 Unity UGUI 到 Unreal UMG 的交互与高效实践:UI 事件、坐标系适配与性能优化
  • WinContig:高效磁盘碎片整理工具
  • 基于蓝牙的stm32智能火灾烟雾报警系统设计
  • Golang云端编程入门指南:前沿框架与技术全景解析
  • 访问控制基础与模型综述
  • Python自学笔记11 Numpy的索引和切片
  • Sui 主网升级至 V1.54.2
  • Lucene 与 Elasticsearch:从底层引擎到分布式搜索平台的演进
  • 虚幻引擎5(UE5)Android端游戏开发全流程指南:从环境配置到项目发布
  • Spring Boot测试陷阱:失败测试为何“传染”其他用例?
  • 在PC机上使用虚幻引擎5(UE5)开发第一款游戏的完整入门指南
  • HTTP请求中的CGI请求与登录注册机制
  • Golang云端编程深度指南:架构本质与高阶实践
  • 动态规划--编译距离
  • 包裹堆叠场景漏检率↓79%!陌讯多目标追踪算法在智慧物流的实践优化
  • C/C++数据结构之循环链表
  • Redis详解--基本篇
  • 手写MyBatis第31弹-用工厂模式重构MyBatis的SqlSession创建过程
  • 数据可视化——matplotlib库