ODBObject-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 需安装libmysqlclientPostgreSQL 需安装libpq配置 C 编译环境确保编译器支持 C11 及以上如 GCC、Clang、MSVC。2项目依赖链接 ODB 核心库odb和对应数据库驱动库如odb-mysql、odb-sqlite包含 ODB 头文件路径#include odb/database.hxx等。二、ODB 入门简单对象映射1. 定义持久化类首先定义一个 C 类通过 ODB 注解标记为 “持久化类”并指定表名、字段属性1234567891011121314151617181920212223242526272829// person.hxx#include string#include odb/core.hxx // ODB核心头文件// 标记为持久化类对应数据库表person#pragma db object table(person)classPerson{public:Person() {}// 必须提供默认构造函数Person(conststd::string name,intage,conststd::string email): name_(name), age_(age), email_(email) {}// 访问器方法conststd::string name()const{returnname_; }intage()const{returnage_; }conststd::string email()const{returnemail_; }private:// 主键auto表示自增#pragma db id autounsignedlongid_;// 普通字段可指定列名、约束如not_null#pragma db column(name) not_nullstd::string name_;#pragma db column(age)intage_;#pragma db column(email) unique // 唯一约束std::string email_;// ODB需要访问私有成员声明友元friendclassodb::access;};2. 生成数据库访问代码ODB 通过编译器odb命令分析注解生成持久化类的数据库操作代码12# 针对MySQL生成代码输出person-odb.hxx和person-odb.cxxodb -d mysql --generate-query --generate-schema person.hxx-d mysql指定数据库类型可选sqlite、pgsql等--generate-query生成查询支持代码--generate-schema生成建表 SQL 语句。3. 基础数据库操作CRUD1初始化数据库连接123456789101112#include odb/database.hxx#include odb/mysql/database.hxx // MySQL驱动// 创建数据库连接MySQL示例std::unique_ptrodb::database db(newodb::mysql::database(root,// 用户名password,// 密码test_db,// 数据库名localhost,// 主机3306// 端口));2插入数据Create12345#include person-odb.hxx // 生成的代码Person p(Alice, 25,aliceexample.com);odb::transaction t(db-begin());// 开启事务db-persist(p);// 插入对象到数据库t.commit();// 提交事务3查询数据Read主键查询1234odb::transaction t(db-begin());std::shared_ptrPerson p db-loadPerson(1);// 根据主键1查询std::cout Name: p-name() , Age: p-age() std::endl;t.commit();条件查询12345678910111213#include odb/query.hxx#include odb/session.hxxodb::session s;// 查询需开启sessionodb::transaction t(db-begin());// 构建查询age 20 且 name LIKE A%odb::queryPerson q(odb::queryPerson::age 20 odb::queryPerson::name.like(A%));// 执行查询并遍历结果for(auto p : db-queryPerson(q))std::cout p.name() : p.email() std::endl;t.commit();4更新数据Update12345odb::transaction t(db-begin());std::shared_ptrPerson p db-loadPerson(1);p-age_ 26;// 修改对象需将age_改为public或提供setterdb-update(*p);// 更新数据库t.commit();5删除数据Delete123odb::transaction t(db-begin());db-erasePerson(1);// 根据主键删除t.commit();三、ODB 进阶特性1. 关联映射1一对一关联One-to-One例如Person关联Address1234567891011121314// address.hxx#pragma db objectclassAddress{// ... 字段定义主键id_street_city_等};// person.hxx中添加关联#pragma db objectclassPerson{// ... 其他字段#pragma db one_to_one // 一对一关联odb::lazy_ptrAddress address_;// 懒加载访问时才查询};2一对多关联One-to-Many例如Department包含多个Employee12345678910111213141516// employee.hxx#pragma db objectclassEmployee{// ... 字段#pragma db many_to_one // 多对一反向关联odb::ptrDepartment dept_;};// department.hxx#pragma db objectclassDepartment{// ... 字段#pragma db one_to_many(mapped_by dept_) // 一对多指定反向关联字段std::vectorodb::ptrEmployee employees_;};2. 继承映射ODB 支持类继承的表映射分为三种策略单表策略所有子类映射到同一张表通过discriminator区分Joined 策略父类和子类分别映射到不同表查询时关联Table-per-class 策略每个子类映射到独立表。