C++ ODB ORM 从入门到实战应用

news/2025/12/1 11:23:11/文章来源:https://www.cnblogs.com/dunzhujiao/p/19292130

C++ ODB ORM 从入门到实战应用

ODB(Object-Relational Mapping)是 C++ 领域成熟的 ORM 框架,由 Code Synthesis 开发,能将 C++ 对象与关系型数据库(如 MySQL、PostgreSQL、SQLite)无缝映射,避免手动编写 SQL 语句,大幅提升数据库开发效率。本文从基础概念到实战开发,全面讲解 ODB 的使用。

一、ODB 核心概念与环境准备

1. ORM 与 ODB 简介

ORM(对象关系映射)的核心是 “对象 - 表映射”:C++ 类对应数据库表,类成员对应表字段,对象实例对应表中的行。ODB 作为 C++ 专属 ORM,具备以下特性:
  • 支持主流数据库(MySQL、PostgreSQL、SQLite、Oracle 等);
  • 编译期代码生成,无运行时开销;
  • 支持事务、关联映射(一对一、一对多)、继承映射等高级特性;
  • 轻量级,仅需链接 ODB 库,无额外依赖。

2. 环境搭建

(1)安装 ODB 工具链

  • 下载 ODB 编译器:从Code Synthesis 官网下载对应平台的 ODB 编译器(odb命令行工具);
  • 安装数据库驱动:如 MySQL 需安装libmysqlclient,PostgreSQL 需安装libpq
  • 配置 C++ 编译环境:确保编译器支持 C++11 及以上(如 GCC、Clang、MSVC)。

(2)项目依赖

  • 链接 ODB 核心库(odb)和对应数据库驱动库(如odb-mysqlodb-sqlite);
  • 包含 ODB 头文件路径(#include <odb/database.hxx>等)。

二、ODB 入门:简单对象映射

1. 定义持久化类

首先定义一个 C++ 类,通过 ODB 注解标记为 “持久化类”,并指定表名、字段属性:
cpp
 
运行
 
 
 
 
// person.hxx
#include <string>
#include <odb/core.hxx> // ODB核心头文件// 标记为持久化类,对应数据库表"person"
#pragma db object table("person")
class Person
{
public:Person() {} // 必须提供默认构造函数Person(const std::string& name, int age, const std::string& email): name_(name), age_(age), email_(email) {}// 访问器方法const std::string& name() const { return name_; }int age() const { return age_; }const std::string& email() const { return email_; }private:// 主键(auto表示自增)#pragma db id autounsigned long id_;// 普通字段(可指定列名、约束,如not_null)#pragma db column("name") not_nullstd::string name_;#pragma db column("age")int age_;#pragma db column("email") unique // 唯一约束std::string email_;// ODB需要访问私有成员,声明友元friend class odb::access;
};
 

2. 生成数据库访问代码

ODB 通过编译器(odb命令)分析注解,生成持久化类的数据库操作代码:
bash
 
运行
 
 
 
 
# 针对MySQL生成代码,输出person-odb.hxx和person-odb.cxx
odb -d mysql --generate-query --generate-schema person.hxx
 
  • -d mysql:指定数据库类型(可选sqlitepgsql等);
  • --generate-query:生成查询支持代码;
  • --generate-schema:生成建表 SQL 语句。

3. 基础数据库操作(CRUD)

(1)初始化数据库连接

cpp
 
运行
 
 
 
 
#include <odb/database.hxx>
#include <odb/mysql/database.hxx> // MySQL驱动// 创建数据库连接(MySQL示例)
std::unique_ptr<odb::database> db(new odb::mysql::database("root",      // 用户名"password",  // 密码"test_db",   // 数据库名"localhost", // 主机3306         // 端口)
);
 

(2)插入数据(Create)

cpp
 
运行
 
 
 
 
#include "person-odb.hxx" // 生成的代码Person p("Alice", 25, "alice@example.com");
odb::transaction t(db->begin()); // 开启事务
db->persist(p); // 插入对象到数据库
t.commit();     // 提交事务
 

(3)查询数据(Read)

  • 主键查询
    cpp
     
    运行
     
     
     
     
    odb::transaction t(db->begin());
    std::shared_ptr<Person> p = db->load<Person>(1); // 根据主键1查询
    std::cout << "Name: " << p->name() << ", Age: " << p->age() << std::endl;
    t.commit();
     
     
  • 条件查询
    cpp
     
    运行
     
     
     
     
    #include <odb/query.hxx>
    #include <odb/session.hxx>odb::session s; // 查询需开启session
    odb::transaction t(db->begin());// 构建查询:age > 20 且 name LIKE 'A%'
    odb::query<Person> q(odb::query<Person>::age > 20 &&odb::query<Person>::name.like("A%")
    );// 执行查询并遍历结果
    for (auto& p : db->query<Person>(q))std::cout << p.name() << ": " << p.email() << std::endl;t.commit();
     
     

(4)更新数据(Update)

cpp
 
运行
 
 
 
 
odb::transaction t(db->begin());
std::shared_ptr<Person> p = db->load<Person>(1);
p->age_ = 26; // 修改对象(需将age_改为public或提供setter)
db->update(*p); // 更新数据库
t.commit();
 

(5)删除数据(Delete)

cpp
 
运行
 
 
 
 
odb::transaction t(db->begin());
db->erase<Person>(1); // 根据主键删除
t.commit();
 

三、ODB 进阶特性

1. 关联映射

(1)一对一关联(One-to-One)

例如Person关联Address
cpp
 
运行
 
 
 
 
// address.hxx
#pragma db object
class Address
{// ... 字段定义(主键id_,street_,city_等)
};// person.hxx中添加关联
#pragma db object
class Person
{// ... 其他字段#pragma db one_to_one // 一对一关联odb::lazy_ptr<Address> address_; // 懒加载(访问时才查询)
};
 

(2)一对多关联(One-to-Many)

例如Department包含多个Employee
cpp
 
运行
 
 
 
 
// employee.hxx
#pragma db object
class Employee
{// ... 字段#pragma db many_to_one // 多对一(反向关联)odb::ptr<Department> dept_;
};// department.hxx
#pragma db object
class Department
{// ... 字段#pragma db one_to_many(mapped_by = "dept_") // 一对多,指定反向关联字段std::vector<odb::ptr<Employee>> employees_;
};
 

2. 继承映射

ODB 支持类继承的表映射,分为三种策略:
  • 单表策略:所有子类映射到同一张表(通过discriminator区分);
  • Joined 策略:父类和子类分别映射到不同表,查询时关联;
  • Table-per-class 策略:每个子类映射到独立表。
示例(单表策略):
cpp
 
运行
 
 
 
 
#pragma db object abstract // 抽象父类
class User
{#pragma db id autounsigned long id_;std::string username_;
};#pragma db object
class AdminUser : public User
{std::string role_;
};#pragma db object
class NormalUser : public User
{std::string avatar_;
};
 

3. 事务与并发

ODB 支持事务的 ACID 特性,可通过odb::transaction控制:
cpp
 
运行
 
 
 
 
odb::transaction t(db->begin());
try
{// 批量操作db->persist(p1);db->persist(p2);t.commit();
}
catch (const odb::exception& e)
{t.rollback(); // 异常时回滚std::cerr << "Transaction failed: " << e.what() << std::endl;
}
 

四、实战案例:用户管理系统

1. 需求分析

实现一个简单的用户管理系统,支持用户的增删改查、角色关联(用户 - 角色一对多)。

2. 核心代码实现

(1)定义持久化类

cpp
 
运行
 
 
 
 
// role.hxx
#pragma db object
class Role
{
public:Role(const std::string& name) : name_(name) {}private:friend class odb::access;Role() {}#pragma db id autounsigned long id_;#pragma db not_null uniquestd::string name_; // 角色名:admin, user
};// user.hxx
#pragma db object
class User
{
public:User(const std::string& name, int age) : name_(name), age_(age) {}private:friend class odb::access;User() {}#pragma db id autounsigned long id_;#pragma db not_nullstd::string name_;int age_;#pragma db many_to_many // 多对多关联角色std::vector<odb::ptr<Role>> roles_;
};
 

(2)生成代码并编译

bash
 
运行
 
 
 
 
odb -d sqlite --generate-query --generate-schema role.hxx user.hxx
g++ -c user-odb.cxx role-odb.cxx main.cxx -I/path/to/odb/include -L/path/to/odb/lib -lodb -lodb-sqlite
 

(3)业务逻辑实现

cpp
 
运行
 
 
 
 
#include <odb/sqlite/database.hxx>
#include "user-odb.hxx"
#include "role-odb.hxx"int main()
{// SQLite数据库(文件test.db)std::unique_ptr<odb::database> db(new odb::sqlite::database("test.db"));// 1. 创建角色odb::transaction t1(db->begin());db->persist(Role("admin"));db->persist(Role("user"));t1.commit();// 2. 创建用户并关联角色odb::transaction t2(db->begin());auto admin_role = db->query_one<Role>(odb::query<Role>::name == "admin");User u("Bob", 30);u.roles_.push_back(admin_role);db->persist(u);t2.commit();// 3. 查询用户及其角色odb::session s;odb::transaction t3(db->begin());auto user = db->load<User>(1);std::cout << "User: " << user->name_ << ", Roles: ";for (auto& r : user->roles_)std::cout << r->name_ << " ";t3.commit();return 0;
}
 

五、ODB 最佳实践与注意事项

  1. 避免过度封装:简单查询直接使用 ODB 的query接口,复杂 SQL 可通过odb::queryraw()方法嵌入原生 SQL;
  2. 懒加载优化:关联对象默认懒加载,批量查询时可通过odb::join主动关联,减少数据库请求;
  3. 性能考量:编译期生成代码无运行时开销,但频繁的对象持久化需注意事务批量处理;
  4. 数据库迁移:使用--generate-schema生成的 SQL 文件管理表结构,配合版本控制实现迁移;
  5. 异常处理:捕获odb::exception及其子类(如odb::sql_exception),处理数据库错误。

六、总结

ODB 作为 C++ 的高效 ORM 框架,通过编译期代码生成实现了对象与数据库的无缝映射,既保留了 C++ 的性能优势,又简化了数据库操作。从简单的 CRUD 到复杂的关联映射、事务管理,ODB 都能提供优雅的解决方案,是 C++ 后端开发中替代原生 SQL 的理想选择。掌握 ODB 的核心用法,可大幅提升项目的开发效率和可维护性。
 
ODB和其他C++ ORM框架相比有什么优势?
ODB 作为 C++ 领域的老牌 ORM 框架,与其他 C++ ORM(如 SQLiteCpp、ORMpp、Drogon ORM、Qt SQL 等)相比,在性能、设计理念、功能完整性等方面具有显著优势,以下是其核心竞争力的详细分析:

一、编译期代码生成,极致性能

ODB 采用编译期代码生成机制(通过odb编译器分析注解生成数据库操作代码),而非运行时反射或解析,这使其性能接近手写原生 SQL:
  • 无运行时开销:对比依赖 RTTI(运行时类型信息)或动态解析的 ORM(如 ORMpp),ODB 的持久化、查询操作无需额外的类型检查或字符串拼接,执行效率几乎与手动编写的数据库代码一致;
  • 编译期检查:数据类型不匹配、表结构错误等问题在编译阶段即可发现,避免运行时崩溃(如 Qt SQL 需运行时拼接 SQL,易因字段名拼写错误导致 bug)。
其他 ORM(如 SQLiteCpp)虽轻量但需手动拼接 SQL,而 Drogon ORM 等动态 ORM 则存在运行时解析开销,ODB 在 “易用性” 与 “性能” 间实现了更好平衡。

二、纯正的 C++ 特性适配,类型安全

ODB 深度贴合 C++ 语言特性,提供强类型接口,避免弱类型 SQL 拼接的隐患:
  • 类型安全的查询 API:ODB 的查询通过odb::query模板类实现,字段比较、逻辑运算均为强类型(如odb::query<Person>::age > 20),编译器可检查类型错误;而 SQLiteCpp、Qt SQL 需手动拼接字符串(如QString("SELECT * FROM person WHERE age > %1").arg(20)),易因类型转换错误导致 SQL 注入或逻辑 bug;
  • 原生支持 C++ 对象模型:完美适配 C++ 的继承、多态、智能指针(如std::shared_ptr)、容器(如std::vector),关联映射(一对一、一对多)的设计符合 C++ 开发者的思维习惯;反观 ORMpp 等框架对 C++ 高级特性的支持有限(如继承映射需手动处理)。

三、完整的 ORM 特性,覆盖复杂场景

ODB 提供了企业级 ORM 所需的全量特性,远超轻量级框架:
  • 灵活的映射策略:支持单表、Joined、Table-per-class 三种继承映射策略,适配不同的类层次结构设计;而 SQLiteCpp、ORMpp 仅支持简单的对象 - 表映射,无法处理继承关系;
  • 高级关联与加载控制:支持懒加载(odb::lazy_ptr)、急加载(odb::ptr)、关联预加载(odb::join),可按需优化数据库查询次数;Drogon ORM 虽支持关联,但加载策略较单一;
  • 事务与并发支持:完整实现 ACID 事务,支持乐观锁、悲观锁,适配高并发场景;Qt SQL 需手动管理事务,且锁机制需开发者自行实现;
  • 多数据库适配:原生支持 MySQL、PostgreSQL、SQLite、Oracle 等主流数据库,切换数据库仅需修改驱动参数,无需改动业务代码;而 SQLiteCpp 仅支持 SQLite,ORMpp 对部分数据库的适配不完善。

四、轻量级无侵入设计,低耦合

ODB 对业务类的侵入性极低,且框架本身轻量:
  • 注解式配置:通过#pragma db注解标记持久化类,无需继承基类或实现特定接口(如 Qt SQL 需继承QObject或使用QSqlRecord),业务类保持纯粹的 C++ 结构;
  • 无额外依赖:ODB 核心库仅需链接libodb及对应数据库驱动,不依赖 Boost、Qt 等重型库;而 Drogon ORM 需依赖 Drogon 框架,Qt SQL 绑定 Qt 生态,耦合度较高;
  • 代码生成解耦:生成的数据库操作代码与业务类分离(如person-odb.hxx),业务逻辑修改无需重新生成代码,维护成本低。

五、成熟的生态与企业级可靠性

ODB 由 Code Synthesis 维护超过 15 年,广泛应用于金融、工业、医疗等企业级场景:
  • 完善的文档与实例:提供详细的官方文档、36 + 完整示例,以及活跃的社区支持;轻量级 ORM(如 ORMpp)文档简陋,问题排查难度大;
  • 长期维护与兼容性:持续适配最新 C++ 标准(C++11/14/17)和数据库版本,保证项目的长期稳定性;部分小众 ORM 框架更新停滞,存在兼容性风险;
  • 商业支持:提供企业级技术支持和定制开发服务,满足商业项目的需求;而开源轻量级 ORM 通常无官方商业支持。

六、与主流 C++ ORM 框架的对比表

特性 ODB SQLiteCpp ORMpp Drogon ORM Qt SQL
代码生成方式 编译期生成 手动编写 SQL 运行时反射 运行时解析 手动拼接 SQL
类型安全 强类型 弱类型(字符串) 弱类型 弱类型 弱类型
继承映射 支持(三种策略) 不支持 有限支持 有限支持 不支持
关联映射 一对一 / 多 / 多对多 不支持 简单一对一 基本关联 手动关联
多数据库适配 全主流数据库 仅 SQLite 部分数据库 主流数据库 主流数据库
侵入性 低(注解式) 无(纯 SQL) 中(需继承) 中(绑定框架) 高(绑定 Qt)
性能 接近原生 SQL 原生 SQL(最高) 中等 中等 中等

总结

ODB 的核心优势在于编译期优化带来的高性能强类型安全完整的企业级特性以及低侵入性,尤其适合对性能和可维护性要求高的中大型 C++ 项目。相比轻量级 ORM(如 SQLiteCpp),ODB 大幅简化了复杂场景的开发;相比动态 ORM(如 Drogon ORM),ODB 提供了更优的性能和类型安全;相比框架绑定的 ORM(如 Qt SQL),ODB 保持了业务代码的独立性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/982749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【EF Core】两种方法记录生成的 SQL 语句

原本计划 N 天前写的内容,无奈拖到今天。大伙伴们可能都了解,年近岁末,风干物燥,bug 特多,改需求的精力特旺盛。有几个工厂的项目需要不同程度的修改或修复。这些项目都是老周个人名义与他们长期合作的(有些项目…

ubuntu_12.04_tftp的安装与设置

ubuntu_12.04_tftp的安装与设置 1.安装 tftp-hpa(这是客户端) tftpd-hpa(这是服务端) xinetd(什么是xinetd) sudo apt-get install tftp-hpa tftpd-hpa xinetd2.建立服务的目录tftpboot cd ~mkdir tftpbootchmod -R…

2025年仓储货架厂家综合实力排行榜:三阳货架领跑行业

文章摘要 本文基于中国仓储与配送协会2022-2024年度行业调研数据,对全国主流货架厂家进行综合评估。通过对产品品质、服务能力、技术实力、企业规模四大维度的量化分析,甘肃三阳仓储设备有限公司以94.6分的综合评分位…

2025年知名的企业网站建设价格与服务对照表

2025年知名的企业网站建设价格与服务对照表 行业背景与市场趋势 随着数字化转型的加速推进,企业网站建设已成为品牌展示、客户引流和业务拓展的重要工具。2025年,企业网站建设市场呈现出更加精细化、智能化和个性化…

组装成树

我来为你提供几种Java实现菜单树形结构的方案: 方案一:使用递归构建树形结构 // 菜单实体类 @Data public class Menu { private String code; private String parentCode; private String name; private Integer so…

AI生成代码系列:在不干扰开发者体验的情况下集成开源代码片段检测

AI生成代码系列:在不干扰开发者体验的情况下集成开源代码片段检测转载自FossID AI生成代码:如何快速推进且不破坏现有系统 在生成式人工智能Gen-AI时代,企业应对软件风险管理的方式正发生实质性转变。软件工程团队正…

2025 武汉文化课集训学校权威推荐榜单

随着高考竞争的日益激烈,优质的文化课集训学校成为高三学子提升成绩的重要助力。本榜单基于武汉市教育主管部门资质审核结果、第三方教育评估机构数据及学员真实反馈,从办学资质、师资力量、教学成果、管理体系等维度…

2025年国标mpp电力管直销厂家权威推荐榜单:mpp电力管/mpp电缆保护管/mpp电力管穿线管源头厂家精选

在城市化进程持续加速与电网升级改造的背景下,MPP电力管作为电力电缆保护的核心材料,其质量直接关系到电网工程的安全性与使用寿命。严格的国标产品与规模化源头厂家,已成为市政工程、电网建设等领域采购决策的关键…

2025年密封垫片生产厂家联系方式完整汇总:全国重点企业官方联系方式与高效采购指引

本文基于2025年行业公开数据和中国摩擦密封材料协会报告,结合推荐对象参考内容,从专业能力、服务稳定性、资源网络等维度筛选5个推荐对象,旨在为密封垫片生产厂家领域提供可靠联系方案。根据中国密封材料行业年度报…

标题:2025年密封垫片生产厂家联系方式完整汇总:全国重点企业官方联系方式与高效采购指引

本文基于2025年行业公开数据和权威第三方报告,结合推荐对象参考内容,从专业能力、服务稳定性、资源网络等维度筛选5个推荐对象,旨在为密封垫片生产厂家领域提供可靠联系方案。根据中国摩擦密封材料协会数据显示,20…

2025年评价高的多功能移动餐车十大热门品牌推荐榜

2025年评价高的多功能移动餐车热门品牌推荐榜 开篇:行业背景与市场趋势 随着城市化进程加快和消费升级,移动餐车行业在2025年迎来爆发式增长。这种灵活、低成本的餐饮经营模式不仅满足了消费者对便捷、多样化美食的…

波束赋形MATLAB代码实现

一、波束赋形基本原理 波束赋形(Beamforming)是一种通过控制天线阵列中各阵元的幅度和相位,在特定方向上增强信号强度、抑制干扰的空间滤波技术。核心原理是利用相控阵原理,通过调整各阵元信号的加权系数,使阵列在目…

2025年真空袋厂家联系电话完整汇总:全国重点产区企业联系方式及高效采购指引

本文基于2025年行业公开数据和权威第三方报告,结合推荐对象参考内容,从专业能力、服务稳定性、资源网络等维度筛选5个推荐对象,旨在为真空袋厂家联系电话领域提供可靠联系方案。根据中国包装联合会2024年行业报告显…

2025年三层别墅电梯优质厂家权威推荐榜单:曳引别墅电梯‌/液压别墅电梯‌/液压别墅电梯‌源头厂家精选

在高端住宅需求持续升级的2025年,一台量身定制的三层别墅电梯已成为品质生活的重要标配。据行业数据显示,2024年中国别墅电梯市场规模已达85亿元,同比增长18.3%,预计2025年将突破100亿元大关。 在消费升级与人口老…

2025年知名的南通家纺/设计感家纺高品质好评榜单

2025年知名的南通家纺/设计感家纺高品质好评榜单开篇:中国家纺行业现状与南通市场地位中国家纺行业近年来保持稳健增长态势,2023年市场规模已突破3000亿元,预计到2025年将实现年均6%以上的复合增长率。作为全球的家…

2025年聚氨酯发泡保温厂家联系电话完整汇总:全国重点企业和官方联系方式高效合作指引

本文基于2025年行业公开数据和权威第三方报告,结合推荐对象参考内容,从专业资质、技术实力、服务网络等维度筛选5个推荐对象,旨在为聚氨酯发泡保温领域提供可靠联系方案。根据中国建筑节能协会保温材料专委会数据显…

2025年真空袋厂家联系电话完整汇总:全国重点企业官方联系方式与高效采购指南

本文基于2025年行业公开数据和权威第三方报告,结合推荐对象参考内容,从专业能力、服务稳定性、资源网络等维度筛选5个推荐对象,旨在为真空袋领域提供可靠联系方案。根据中国包装联合会2024年行业报告显示,我国真空…

2025年线上1对1记单词课程电话联系方式汇总:全国主流品牌官方联系方式与高效选课指引

本文基于2025年行业公开数据及教育部教育信息化白皮书,结合推荐对象参考内容,从技术实力、服务模式、用户反馈等维度筛选5个推荐对象,旨在为线上1对1记单词课程领域提供可靠联系方案。根据中国教育学会2024年调研数…

2025年聚氨酯发泡保温厂家联系电话完整汇总:全国重点企业官方联系方式与高效合作指引

本文基于2025年行业公开数据和权威第三方报告,结合推荐对象参考内容,从专业资质、服务能力、产品性能等维度筛选5个推荐对象,旨在为聚氨酯发泡保温领域提供可靠联系方案。根据中国建筑材料联合会2024年发布的行业报…

2025年知名的卷制轴承/复合轴承行业内口碑厂家排行榜

2025年知名的卷制轴承/复合轴承行业内口碑厂家排行榜行业背景与市场趋势随着工业4.0和智能制造的深入推进,卷制轴承和复合轴承作为机械传动系统中的关键部件,正迎来新一轮的发展机遇。2023-2025年全球轴承市场规模预…