ODB安装与使用

目录

[一.ODB2.5 版本安装:](#一.ODB2.5 版本安装:)

[安装 build2:](#安装 build2:)

[安装 odb-compiler](#安装 odb-compiler)

[安装 mysql 和客户端开发包](#安装 mysql 和客户端开发包)

[安装 boost profile 库](#安装 boost profile 库)

总体打包安装:

总体卸载:

总体升级:

二.ODB编程

三.测试样例

四.总结


一.ODB2.5****版本安装:

整个安装过程在 3 - 5 小时左右, 视网络情况而定。

安装build2

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

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

bash 复制代码
 curl -sSfO https://download.build2.org/0.17.0/build2-install-0.17.0.sh
bash 复制代码
sh build2-install-0.17.0.sh

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

bash 复制代码
sh build2-install-0.17.0.sh --timeout 1800

安装****odb-compiler

bash 复制代码
sudo apt-get install gcc-11-plugin-dev
bash 复制代码
mkdir odb-build && cd odb-build
bash 复制代码
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
bash 复制代码
cd odb-gcc-N
bash 复制代码
bpkg build odb@https://pkg.cppget.org/1/beta
cpp 复制代码
bpkg test odb
bash 复制代码
bpkg install odb
bash 复制代码
odb --version
bash 复制代码
#如果报错了,找不到 odb,那就在执行下边的命令
sudo echo 'export PATH=${PATH}:/usr/local/bin' >> ~/.bashrc
bash 复制代码
export PATH=${PATH}:/usr/local/bin
bash 复制代码
odb --version

安装ODB运行时库:

bash 复制代码
cd ..

bpkg create -d libodb-gcc-N cc
\
 config.cxx=g++ \
 config.cc.coptions=-O3 \
 config.install.root=/usr/ \
 config.install.sudo=sudo

cd libodb-gcc-N

bpkg add https://pkg.cppget.org/1/beta

bpkg fetch

bpkg build libodb

bpkg build libodb-mysql

安装mysql和客户端开发包

bash 复制代码
sudo apt install mysql-server
sudo apt install -y libmysqlclient-dev

配置 mysql

cpp 复制代码
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

修改 root 用户密码

bash 复制代码
sudo cat /etc/mysql/debian.cnf
sudo mysql -u debian-sys-maint -p

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH
       mysql_native_password BY 'xxxxxx';

mysql> FLUSH PRIVILEGES;

重启 mysql,并设置开机启动

bash 复制代码
sudo systemctl restart mysql
sudo systemctl enable mysql

安装boost profile

bash 复制代码
bpkg build libodb-boost

总体打包安装:

bash 复制代码
bpkg install --all --recursive

总体卸载:

bash 复制代码
bpkg uninstall --all --recursive

总体升级:

bash 复制代码
bpkg fetch
bpkg status
bpkg uninstall --all --recursive
bpkg build --upgrade --recursive
bpkg install --all --recursive

二.ODB编程

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

  1. #pragma db object:

○ 用于声明一个类是数据库对象,即这个类将映射到数据库中的一个表。
2. #pragma db table("table_name"):

○ 指定类映射到数据库中的表名。如果不指定,则默认使用类名。

  1. #pragma db id:

○ 标记类中的一个成员变量作为数据库表的主键。

  1. #pragma db column("column_name"):

○ 指定类成员映射到数据库表中的列名。如果不指定,则默认使用成员变量的名字。

  1. #pragma db view:

○ 用于声明一个类是一个数据库视图,而不是一个表。

  1. #pragma db session:

○ 用于声明一个全局或成员变量是数据库会话。

  1. #pragma db query("query"):

○ 用于定义自定义的查询函数。

  1. #pragma db index("index_name"):

○ 指定成员变量应该被索引。

  1. #pragma db default("default_value"):

○ 指定成员变量的默认值。

  1. #pragma db unique:

○ 指定成员变量或一组变量应该具有唯一性约束。

  1. #pragma db not_null:

○ 指定成员变量不允许为空。

  1. #pragma db auto:

○ 指定成员变量的值在插入时自动生成(例如,自动递增的主键)。

  1. #pragma db transient:

○ 指定成员变量不应该被持久化到数据库中。

  1. #pragma db type("type_name"):

○ 指定成员变量的数据库类型。

  1. #pragma db convert("converter"):

○ 指定用于成员变量的自定义类型转换器。

  1. #pragma db pool("pool_name"):
    ○ 指定用于数据库连接的连接池。

  2. #pragma db trigger("trigger_name"):

○ 指定在插入、更新或删除操作时触发的触发器。

三.测试样例

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

cpp 复制代码
#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 = 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;
};

// // #pragma db view query("select name from Student where id = 1")
// // struct all_name
// // {
// //     std::string name;
// // };

// #pragma db view object(Student) query((?))
// struct all_name
// {
//     // std::string name;
//     unsigned long id;
//     unsigned long sn;
//     std::string name;
//     odb::nullable<unsigned short> age;
//     unsigned long classes_id;
// };

// odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time student.hxx

最下面有编译这个hxx文件的命令。

编写测试文件:main.cc

cpp 复制代码
#include <string>
#include <memory>  // std::auto_ptr
#include <cstdlib> // std::exit
#include <iostream>
#include <gflags/gflags.h>
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include <odb/tracer.hxx>

#include "student.hxx"
#include "student-odb.hxx"

DEFINE_string(host, "127.0.0.1", "这是Mysql服务器地址");
DEFINE_int32(port, 3306, "这是Mysql服务器端口"); //
DEFINE_string(db, "test", "数据库默认库名称");
DEFINE_string(user, "root", "这是Mysql用户名");
DEFINE_string(pswd, "123456789ylj.", "这是Mysql密码");
DEFINE_string(cset, "utf8", "这是Mysql客户端字符集");
DEFINE_int32(max_pool, 3, "这是Mysql连接池最大连接数量");

void insertClass(odb::mysql::database& db)
{
    try
    {
        //开启一个事务
        odb::transaction trans(db.begin());
        Classes c1("一年级一班");
        Classes c2("一年级二班");
        db.persist(c1);
        db.persist(c2);
        //提交事务
        trans.commit();
    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}

void insertStudent(odb::mysql::database& db)
{
    try
    {
        //开启一个事务
        odb::transaction trans(db.begin());
        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);
        //提交事务
        trans.commit();
    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}

Student selectStudent(odb::mysql::database& db)
{
    Student ret;
    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::cerr << "数据量不对!\n";
            return Student();
        }
        ret = *r.begin();
        //提交事务
        trans.commit();
    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
        return Student();
    }
    return ret;
}

void removeStudent(odb::mysql::database& db)
{
    try 
    {
        //获取事务对象开启事务
        odb::transaction trans(db.begin());
        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 classesStudent(odb::mysql::database& db)
{
    try
    {   
        //开启一个事务
        odb::transaction trans(db.begin());
        typedef odb::query<struct classes_student> query;
        typedef odb::result<struct classes_student> result;
        result r = db.query<struct classes_student>();
        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;
        }
        //提交事务
        trans.commit();
    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}

void allStudent(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>());
        for(auto it = r.begin();it != r.end();it++)
        {
            std::cout << it->name << std::endl;
        }
        //提交事务
        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)
    );
    //4.数据操作
    // insertClass(db);
    // insertStudent(db);
    // auto out = selectStudent(db);
    // std::cout << out.name() << std::endl;
    // std::cout << *out.age() << std::endl;
    // std::cout << out.sn() << std::endl;
    // std::cout << out.classes_id() << std::endl;
    // removeStudent(db);
    // classesStudent(db);
    allStudent(db);
    return 0;
}
cpp 复制代码
c++ -o main main.cc student-odb.cxx -lodb-mysql -lodb -lodb-boost -lgflags

以上一条为编译命令。

目录结构:

内层CMakeLists.txt:

cpp 复制代码
# 1. 添加cmake版本说明
cmake_minimum_required(VERSION 3.1.3)
# 2. 声明工程名称
project(odb-test)

# 3. 检测并生成ODB框架代码
#   1. 添加所需的odb映射代码文件名称
set(odb_path ${CMAKE_CURRENT_SOURCE_DIR}/entity)
set(odb_files student.hxx)
#   2. 检测框架代码文件是否已经生成
set(odb_hxx "")
set(odb_cxx "")
set(odb_srcs "")
foreach(odb_file ${odb_files})
#   3. 如果没有生成,则预定义生成指令 -- 用于在构建项目之间先生成框架代码
    string(REPLACE ".hxx" "-odb.hxx" odb_hxx ${odb_file})
    string(REPLACE ".hxx" "-odb.cxx" odb_cxx ${odb_file})
    if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}${odb_cxx})
        add_custom_command(
            PRE_BUILD
            COMMAND odb
            ARGS -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time ${odb_path}/${odb_file}
            DEPENDS ${odb_path}/${odb_file}
            OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx}
            COMMENT "生成ODB框架代码文件:" ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx}
        )
    endif()
#   4. 将所有生成的框架源码文件名称保存起来 student-odb.cxx classes-odb.cxx
    list(APPEND odb_srcs ${CMAKE_CURRENT_BINARY_DIR}/${odb_cxx})
endforeach()

# 4. 获取源码目录下的所有源码文件
set(src_files "")
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source src_files)
# 5. 声明目标及依赖
add_executable(main ${src_files} ${odb_srcs})
# 6. 设置头文件默认搜索路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/entity)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# 7. 设置需要连接的库
target_link_libraries(main -lodb-mysql -lodb -lodb-boost -lgflags)

#8. 设置安装路径
INSTALL(TARGETS main RUNTIME DESTINATION bin)

外层CMakeLists:

cpp 复制代码
cmake_minimum_required(VERSION 3.1.3)
project(all-test)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test2)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})

测试结果结合mysql命令行客户端进行查看得知结果正确。

四.总结

本篇文章是关于odb框架的安装与介绍,供大家和本人在日常开发中进行参考。

相关推荐
Aurora_wmroy3 分钟前
算法竞赛备赛——【图论】求最短路径——Bellman-Ford & SPFA
数据结构·c++·算法·蓝桥杯·图论
linux修理工11 分钟前
python flusk 监控
开发语言·python
Boop_wu15 分钟前
【Java SE】Object类
java·开发语言
nightunderblackcat19 分钟前
新手向:基于Python的剪贴板历史增强工具
开发语言·python
NineData44 分钟前
NineData新增SQL Server到MySQL复制链路,高效助力异构数据库迁移
数据库·人工智能·mysql
刚入坑的新人编程1 小时前
暑假算法训练.6
数据结构·c++·算法·哈希算法
cccyi71 小时前
c++-string
c++·string
苇柠2 小时前
Java常用API(1)
java·开发语言
意疏2 小时前
浙江大学PTA程序设计C语言基础编程练习题1-5
c语言·开发语言
code bean2 小时前
【C#】C# 事件 两次 -= 会怎么样?
开发语言·c#