[C++项目框架]ODB的简单介绍
ODB
1.ODB2.5安装流程
ODB框架:数据库ORM框架
ORM:
对象关系映射(Object Relational Mapping,简称ORM)用于在面向对象的编程语言和关系型数据库之间进行数据转换。它允许开发者使用对象的方式来操作数据库,而不需要直接编写 SQL 语句。ORM 的主要目的是简化数据库操作,提高开发效率,同时减少错误。
1.安装build2
因为 build2 安装时,有可能会版本更新,从 16 变成 17,或从 17 变 18,因此注意,从官网上看
安装步骤: 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.sh
b84e4114c61aa94c3f6278f010a0dc0536dda65ac39d3863152ec9b64510b86e
$ sh build2-install-0.17.0.sh
安装中因为网络问题,超时失败,解决:将超时时间设置的更长一些
$ sh build2-install-0.17.0.sh --timeout 1800
2. 安装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.
3. 安装 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
4.安装 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
5. 安装 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
2.ODB介绍
ODB 指的是一个 C++ 的 ORM 框架(Object-Relational Mapping),它的作用就是把 C++ 类和关系型数据库(比如 MySQL)里的表进行映射。
也就是说,我们在C++定义一个类,用ODB的编译器对这个类进行处理,ODB 会自动生成对应的 SQL 表结构和访问代码。这样你就可以通过操作 C++ 对象来完成数据库的增删改查,而不用手写 SQL。
3.ODB常见操作介绍
3.1 ODB类型映射


3.2 ODB编程
ODB(Open Database)在数据元结构定义时,使用预处理器指令(#pragma)来提供元数据,这些元数据指示如何将 C++类型映射到数据库模式。这些 #pragma 指令是在 C++代码中使用的,它们不是 C++语言的一部分,而是特定于 ODB 编译器的扩展。(为 C++ 中的类和成员指定数据库的属性)
-
#pragma db object:- 用于声明一个类是数据库对象,即这个类将映射到数据库中的一个表。
-
#pragma db table("table_name"):- 指定类映射到数据库中的表名。如果不指定,默认使用类名。
-
#pragma db id:- 标记类中的一个成员变量作为数据库表的主键。
-
#pragma db column("column_name"):- 指定类成员映射到数据库表中的列名。若不指定,默认使用成员变量的名字。
-
#pragma db view:- 用于声明一个类是数据库视图(而非表)。
-
#pragma db session:- 用于声明一个全局或成员变量是数据库会话。
-
#pragma db query("query"):- 用于定义自定义的查询函数。
-
#pragma db index("index_name"):- 指定成员变量应被索引。
-
#pragma db default("default_value"):- 指定成员变量的默认值。
-
#pragma db unique:- 指定成员变量或一组变量具有唯一性约束。
-
#pragma db not_null:- 指定成员变量不允许为空。
-
#pragma db auto:- 指定成员变量的值在插入时自动生成(如自动递增的主键)。
-
#pragma db transient:- 指定成员变量不应被持久化到数据库中。
-
#pragma db type("type_name"):- 指定成员变量的数据库类型。
-
#pragma db convert("converter"):- 指定用于成员变量的自定义类型转换器。
-
#pragma db pool("pool_name"):- 指定用于数据库连接的连接池。
-
#pragma db trigger("trigger_name"):- 指定在插入、更新或删除操作时触发的触发器。
3.3使用样例
在ODB的使用中我们最关注的有这三点
- 增删改
- 基于sql的查询语句
- 基于多表连接的查询
#include <odb/mysql/database.hxx>
#include <odb/database.hxx>
#include <iostream>
#include "student.hxx"
#include "student-odb.hxx"
#include <gflags/gflags.h>
DEFINE_string(host, "127.0.0.1", "这是Mysql服务器地址");
DEFINE_int32(port, 0, "这是Mysql服务器端口");
DEFINE_string(db, "TestDB", "数据库默认库名称");
DEFINE_string(user, "root", "这是Mysql用户名");
DEFINE_string(pswd, "yangjuntao", "这是Mysql密码");
DEFINE_string(cset, "utf8", "这是Mysql客户端字符集");
DEFINE_int32(max_pool, 3, "这是Mysql连接池最大连接数量");
void insert_classes(odb::mysql::database &db)
{
try
{
// 获取事务对象,开启事务
odb::transaction trans(db.begin());
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
{
// 获取事务对象,开启事务
odb::transaction trans(db.begin());
student s1(1, "张三", 18, 1);
student s2(2, "李四", 19, 1);
student s3(3, "王五", 20, 1);
student s4(4, "赵六", 11, 2);
student s5(5, "田七", 12, 2);
student s6(6, "孙八", 15, 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
{
// 获取事务对象,开启事务
odb::transaction trans(db.begin());
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
{
// 获取事务对象,开启事务
odb::transaction trans(db.begin());
typedef odb::query<student> query;
typedef odb::result<student> result;
result r(db.query<student>(query::name == "张三"));
if (r.size() != 1)
{
std::cout << "数据量不对!" << std::endl;
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)
{
try
{
// 获取事务对象,开启事务
odb::transaction trans(db.begin());
typedef odb::query<student> query;
db.erase_query<student>(query::name=="孙八");
// 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.构造数据库操作database对象
odb::mysql::database db(
FLAGS_user, FLAGS_pswd, FLAGS_db,
FLAGS_host, FLAGS_port, "",
FLAGS_cset, 0, std::move(cpf));
// 4.数据库操作
// insert_student(db);
// auto stu = select_student(db);
// std::cout << stu.sn() << std::endl;
// std::cout << *stu.age() << std::endl;
// std::cout << stu.name() << std::endl;
// std::cout << stu.classes_id() << std::endl;
// stu.age(18888);
// update_student(db, stu);
remove_student(db);
return 0;
}
#pragma once
#include <string>
#include <cstddef> // 用于 std::size_t
#include <boost/date_time/posix_time/posix_time.hpp>
#include <odb/nullable.hxx>
#include <odb/core.hxx>
#pragma db object
class student
{
public:
student()
{
}
student(unsigned long sn, const std::string &name, unsigned short age,
unsigned long cid)
: _sn(sn), _name(name), _age(age), _classes_id(cid) {}
void sn(unsigned long num) { _sn = num; }
unsigned long sn() { return _sn; }
void name(const std::string &name) { _name = name; }
std::string name() { return _name; }
void age(unsigned short num) { _age = num; }
odb::nullable<unsigned short> age() { return _age; }
void classes_id(unsigned long cid) { _classes_id = cid; }
unsigned long classes_id() { return _classes_id; }
private:
friend class odb::access;
#pragma db id auto
unsigned long _id;
#pragma db unique
unsigned long _sn;
std::string _name;
odb::nullable<unsigned short> _age;
#pragma db index
unsigned long _classes_id;
};
#pragma db object
class Classes
{
public:
Classes() {}
Classes(const std::string &name) : _name(name) {}
void name(const std::string &name) { _name = name; }
std::string name() { return _name; }
private:
friend class odb::access;
#pragma db id auto
unsigned long _id;
std::string _name;
};
// 查询所有的学生信息,并显示班级姓名
#pragma db view object(student) \
object(Classes : student::_classes_id == Classes::_id) \
query((?))
struct classes_student
{
#pragma db column(student::_id)
unsigned long _id;
#pragma db column(student::_sn)
unsigned long _sn;
#pragma db column(student::_name)
std::string _name;
#pragma db column(student::_age)
odb::nullable<unsigned short> _age;
#pragma db column(Classes::_name)
std::string _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
更多推荐
所有评论(0)