營(yíng)銷(xiāo)型網(wǎng)站收費(fèi)seo推廣培訓(xùn)課程
目錄
概述
基本工作原理
映射C++對(duì)象到數(shù)據(jù)庫(kù)表
從數(shù)據(jù)庫(kù)中加載對(duì)象
持久化C++對(duì)象到數(shù)據(jù)庫(kù)
ODB常用接口
表創(chuàng)建預(yù)處理
#pragma db
Object
table
數(shù)據(jù)表屬性
id?
auto
column(“xxx”)
type("xxx")
unique
index
null
default(xxx)
?總結(jié)
查詢(xún)預(yù)處理
view?
query
result
database類(lèi)
連接管理接口
?事務(wù)管理接口
對(duì)象存取接口
對(duì)象查詢(xún)接口
類(lèi)型映射與元數(shù)據(jù)接口
數(shù)據(jù)庫(kù)備份與恢復(fù)
基本使用
概述
ODB 庫(kù)的目標(biāo)是提供一個(gè)功能強(qiáng)大且類(lèi)型安全的 ORM 解決方案,使得 C++ 開(kāi)發(fā)者能夠輕松地處理數(shù)據(jù)庫(kù)操作,同時(shí)保留 C++ 中對(duì)象的優(yōu)勢(shì)。它通過(guò) C++ 類(lèi)和數(shù)據(jù)庫(kù)表之間的自動(dòng)映射來(lái)簡(jiǎn)化數(shù)據(jù)庫(kù)的持久化操作。
- 對(duì)象到數(shù)據(jù)庫(kù)的映射:將 C++ 對(duì)象映射到數(shù)據(jù)庫(kù)中的表
- 數(shù)據(jù)庫(kù)到對(duì)象的映射:將數(shù)據(jù)庫(kù)中的記錄自動(dòng)映射為 C++ 對(duì)象,支持一對(duì)一、一對(duì)多、多對(duì)多等關(guān)系
優(yōu)點(diǎn)
- 簡(jiǎn)化代碼:使用 ODB,可以省去手動(dòng)編寫(xiě) SQL 查詢(xún)的繁瑣步驟,減少 SQL 注入和數(shù)據(jù)類(lèi)型轉(zhuǎn)換的錯(cuò)誤
- 類(lèi)型安全:所有操作都使用 C++ 對(duì)象,而不是原始 SQL 字符串,保證了類(lèi)型的安全性
- 支持復(fù)雜數(shù)據(jù)關(guān)系:可以輕松處理對(duì)象間的復(fù)雜關(guān)系(如一對(duì)多、多對(duì)多等)
- 跨平臺(tái)支持:支持多種數(shù)據(jù)庫(kù)和操作系統(tǒng),適合跨平臺(tái)開(kāi)發(fā)
缺點(diǎn)
- 依賴(lài)生成工具:需要使用 ODB 提供的工具來(lái)生成代碼,增加了構(gòu)建過(guò)程的復(fù)雜性
- 性能:雖然 ODB 在設(shè)計(jì)上注重性能,但 ORM 本身的抽象可能會(huì)導(dǎo)致一些性能損失,特別是在處理大量數(shù)據(jù)時(shí)
主要特性
- ?類(lèi)型安全:ODB 提供類(lèi)型安全的映射操作,避免了直接使用 SQL 語(yǔ)句時(shí)可能發(fā)生的類(lèi)型轉(zhuǎn)換錯(cuò)誤。開(kāi)發(fā)者不需要關(guān)心 SQL 的細(xì)節(jié),OIB 會(huì)自動(dòng)處理類(lèi)型映射
- 自動(dòng)生成 SQL 代碼:ODB 會(huì)根據(jù) C++ 類(lèi)和類(lèi)成員的定義自動(dòng)生成 SQL 查詢(xún)語(yǔ)句,開(kāi)發(fā)者不需要顯式地編寫(xiě) SQL 代碼,減少了手動(dòng)編寫(xiě) SQL 的繁瑣性和出錯(cuò)的可能性
- ODB 支持多個(gè)關(guān)系型數(shù)據(jù)庫(kù)
- 復(fù)雜數(shù)據(jù)關(guān)系:ODB 支持對(duì)象之間復(fù)雜的關(guān)系映射,如一對(duì)多、多對(duì)多等關(guān)系,并且能夠自動(dòng)管理外鍵、級(jí)聯(lián)操作等
- 支持繼承和多態(tài):ODB 還支持 C++ 類(lèi)繼承和多態(tài)。你可以使用 ODB 映射繼承層次結(jié)構(gòu)中的類(lèi)到數(shù)據(jù)庫(kù)表,并且支持多態(tài)對(duì)象的持久化
- 查詢(xún)功能:ODB 還支持類(lèi)似于 SQL 的查詢(xún)功能,開(kāi)發(fā)者可以使用 ODB 提供的查詢(xún)接口來(lái)執(zhí)行復(fù)雜的查詢(xún)操作
- 性能:ODB 在生成 SQL 查詢(xún)時(shí)會(huì)盡量?jī)?yōu)化性能,支持批量插入、延遲加載、緩存機(jī)制等特性,從而在性能上做到了較好的平衡
基本工作原理
ODB核心步驟就兩步
- 映射:定義對(duì)象和數(shù)據(jù)庫(kù)表之間的映射關(guān)系
- 持久化:將對(duì)象保存到數(shù)據(jù)庫(kù)或者從數(shù)據(jù)庫(kù)中加載對(duì)象
映射C++對(duì)象到數(shù)據(jù)庫(kù)表
ODB 提供了一個(gè) database
類(lèi)(通常是 odb::database
)來(lái)操作數(shù)據(jù)庫(kù)。開(kāi)發(fā)者可以用它來(lái)保存、加載和查詢(xún) C++ 對(duì)象
db.persist(p)
會(huì)將 Person
對(duì)象的 name_
和 age_
持久化到數(shù)據(jù)庫(kù)中的 Person
表
#include <odb/database.hxx>
#include <odb/transaction.hxx>
#include <odb/sqlite/database.hxx> // 支持 SQLiteint main() {odb::sqlite::database db("example.db", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);Person p("John", 30);// 開(kāi)始事務(wù){(diào)odb::transaction t(db.begin());db.persist(p); // 將對(duì)象持久化到數(shù)據(jù)庫(kù)t.commit();}return 0;
}
從數(shù)據(jù)庫(kù)中加載對(duì)象
b.load<Person>(1)
會(huì)根據(jù)數(shù)據(jù)庫(kù)表中的 ID 為 1 的記錄,自動(dòng)生成一個(gè) Person
對(duì)象
{odb::transaction t(db.begin());std::shared_ptr<Person> p = db.load<Person>(1); // 加載 ID 為 1 的 Person 對(duì)象t.commit();std::cout << "Name: " << p->name() << ", Age: " << p->age() << std::endl;
}
持久化C++對(duì)象到數(shù)據(jù)庫(kù)
ODB 提供了一個(gè) database
類(lèi)(通常是 odb::database
)來(lái)操作數(shù)據(jù)庫(kù)。開(kāi)發(fā)者可以用它來(lái)保存、加載和查詢(xún) C++ 對(duì)象
#include <odb/database.hxx>
#include <odb/transaction.hxx>
#include <odb/sqlite/database.hxx> // 支持 SQLiteint main() {odb::sqlite::database db("example.db", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);Person p("John", 30);// 開(kāi)始事務(wù){(diào)odb::transaction t(db.begin());db.persist(p); // 將對(duì)象持久化到數(shù)據(jù)庫(kù)t.commit();}return 0;
}
ODB常用接口
表創(chuàng)建預(yù)處理
#pragma db
- 功能:這是 ODB 的核心預(yù)處理指令,用來(lái)指定 C++ 類(lèi)或類(lèi)成員與數(shù)據(jù)庫(kù)字段的映射
- 用于定義類(lèi)的整體映射規(guī)則,比如將類(lèi)映射為一個(gè)數(shù)據(jù)庫(kù)表
- 用于定義某個(gè)類(lèi)成員的具體數(shù)據(jù)庫(kù)屬性,比如列名、類(lèi)型、索引、默認(rèn)值等
Object
- 功能:標(biāo)記一個(gè)類(lèi)是數(shù)據(jù)庫(kù)中的一個(gè)持久化對(duì)象(實(shí)體類(lèi))
- 用法:#pragma db object 放在類(lèi)聲明的前面
- 作用:表示
Employee
類(lèi)會(huì)映射到數(shù)據(jù)庫(kù)中的一個(gè)表,果類(lèi)沒(méi)有被標(biāo)記為object
,則 ODB 不會(huì)將其映射為數(shù)據(jù)庫(kù)表
#pragma db object
class Employee {
public:int id;std::string name;
};
table
- 功能:指定類(lèi)映射到數(shù)據(jù)庫(kù)中的表名
- 用法:默認(rèn)情況下,ODB 將類(lèi)的名字(小寫(xiě))作為表名,如果需要自定義表名,那么可以使用table指令
#pragma db object table("employees_table")
class Employee {int id;std::string name;
};
數(shù)據(jù)表屬性
id?
- 功能:指定某字段為數(shù)據(jù)庫(kù)表的主鍵
- 用法:主鍵必須唯一,且必須是整形;#pragma db id放在類(lèi)成員前面,表示該字段是主鍵
class Employee {#pragma db idint id;std::string name;
};
auto
- 功能:表示主鍵字段是自動(dòng)遞增的
- 用法:#pragma db id auto用于主鍵字段,告知ODB讓數(shù)據(jù)庫(kù)自動(dòng)生成該字段
class Employee {#pragma db id autoint id;std::string name;
};
column(“xxx”)
- 功能:將類(lèi)成員變量映射到數(shù)據(jù)庫(kù)表的某個(gè)特定列名
- 用法:默認(rèn)情況下,ODB 使用類(lèi)成員的名字作為數(shù)據(jù)庫(kù)列名;如果需要指定一個(gè)不同的列名,可以使用colum
class Employee {#pragma db column("emp_id")int id;#pragma db column("full_name")std::string name;
};
type("xxx")
- 功能:指定字段在數(shù)據(jù)庫(kù)表中的具體類(lèi)型
- 用法:如果需要覆蓋默認(rèn)映射的字段類(lèi)型,可以用
type
指定
class Employee {#pragma db type("varchar(255)")std::string name;
};
unique
- 功能:標(biāo)記字段為唯一鍵,保證表中該字段的值不會(huì)重復(fù)
- 用法:在需要唯一約束的字段上添加
#pragma db unique
class Employee {#pragma db uniquestd::string email;
};
index
- 功能:為字段創(chuàng)建索引以加速查詢(xún)
- 用法:在需要加速查詢(xún)的字段上使用
#pragma db index
class Employee {#pragma db indexstd::string name;
};
not_null
- 功能:指定字段不能為
NULL
- 用法:在不允許為空的字段上添加
#pragma db not_null
class Employee {#pragma db not_nullstd::string name;
};
null
- 功能:允許字段為
NULL
- 用法:使用
odb::nullable<T>
表示字段可以存儲(chǔ)NULL
值
class Employee {odb::nullable<std::string> middle_name;
};
default(xxx)
- 功能:為字段指定默認(rèn)值
- 用法:在需要設(shè)置默認(rèn)值的字段上使用
#pragma db default(xxx)
class Employee {#pragma db default("Unknown")std::string department;
};
?總結(jié)
// 將該類(lèi)聲明為 ODB 持久化對(duì)象,并映射到數(shù)據(jù)庫(kù)表 "employee_table"
#pragma db object table("employee_table")
class Employee {
public:// 將字段 `id` 映射為數(shù)據(jù)庫(kù)表的主鍵,并且自動(dòng)遞增#pragma db id autoint id;// 將字段 `name` 映射到數(shù)據(jù)庫(kù)表的列名 "full_name",并且設(shè)置為不允許為空#pragma db column("full_name") not_nullstd::string name;// 將字段 `email` 映射到數(shù)據(jù)庫(kù)表的列名 "email_address",并且設(shè)置為唯一值#pragma db column("email_address") uniquestd::string email;// 將字段 `role` 映射為數(shù)據(jù)庫(kù)表的 varchar(20) 類(lèi)型,并設(shè)置默認(rèn)值為 "Staff"#pragma db type("varchar(20)") default("Staff")std::string role;// 定義字段 `phone`,允許為空,使用 odb::nullable<T> 表示odb::nullable<std::string> phone;// 將字段 `department` 創(chuàng)建一個(gè)普通索引,用于加速查詢(xún)#pragma db indexstd::string department;
};
查詢(xún)預(yù)處理
view?
View
是只讀的結(jié)果類(lèi),用于查詢(xún)數(shù)據(jù)并將查詢(xún)結(jié)果映射到特定的結(jié)構(gòu)體或類(lèi)中。View
類(lèi)本質(zhì)上是查詢(xún)的只讀視圖,不能修改底層數(shù)據(jù)
事例1
- 通過(guò)View查詢(xún)學(xué)生信息,然后通過(guò)學(xué)生ID和班級(jí)表ID進(jìn)行關(guān)聯(lián),從而查詢(xún)到對(duì)應(yīng)班級(jí)名稱(chēng)
object(Student)
:指定視圖操作的主要表是Student
object(Classes)
:將Student::_classes_id
與Classes::_id
進(jìn)行關(guān)聯(lián),關(guān)聯(lián)的表命名為classes
#pragma db view object(Student)\object(Classes = classes : Student::_classes_id == classes::_id)\query((?))
struct classes_student {// 將 Student::_id 映射到視圖中的 id 字段#pragma db column(Student::_id)unsigned long id; // 學(xué)生的唯一ID#pragma db column(Student::_sn)unsigned long sn; // 學(xué)號(hào)#pragma db column(Student::_name)std::string name; // 學(xué)生姓名#pragma db column(Student::_age)odb::nullable<unsigned short> age; // 學(xué)生年齡 (可為空)#pragma db column(classes::_name)std::string classes_name; // 班級(jí)名稱(chēng)
};
通過(guò)該視圖可以執(zhí)行SQL查詢(xún)
SELECT Student._id, Student._sn, Student._name, Student._age, Classes._name
FROM Student
JOIN Classes ON Student._classes_id = Classes._id
WHERE <dynamic_condition>;
query
ODB 提供的查詢(xún)接口,用于執(zhí)行動(dòng)態(tài)查詢(xún)并將結(jié)果映射到 C++ 對(duì)象中。查詢(xún)語(yǔ)句可以通過(guò)占位符參數(shù)綁定動(dòng)態(tài)條件
基本用法
typedef odb::query<T> query;
// 查詢(xún)所有年齡大于20的學(xué)生
typedef odb::query<Student> query;
query q = query::age > 20;// 等效下面的SQL語(yǔ)句
SELECT * FROM Student WHERE age > 20;
查詢(xún)所有學(xué)生信息和班級(jí)名稱(chēng)
void queryClassesStudent(database& db) {transaction t(db.begin());// 動(dòng)態(tài)條件odb::result<classes_student> result(db.query<classes_student>("WHERE Student._age >= 18"));// 遍歷結(jié)果for (const auto& record : result) {std::cout << "Student ID: " << record.id<< ", Name: " << record.name<< ", Age: " << (record.age ? *record.age : 0)<< ", Class: " << record.classes_name << std::endl;}t.commit();
}
result
用于存儲(chǔ)和處理查詢(xún)的結(jié)果集。它的模板參數(shù)是查詢(xún)的目標(biāo)類(lèi)型(T
),可以是數(shù)據(jù)庫(kù)表對(duì)象或視圖結(jié)構(gòu)體
typedef odb::result<T> result;
支持類(lèi)似于vector中的相關(guān)操作,迭代器、范圍for等
database類(lèi)
與MySQL中基本操作類(lèi)似,類(lèi)似于對(duì)其操作進(jìn)行二次封裝
連接管理接口
open()
用于打開(kāi)數(shù)據(jù)庫(kù)連接。如果數(shù)據(jù)庫(kù)尚未連接,則建立連接。該方法可能接受連接配置(如數(shù)據(jù)庫(kù)路徑、用戶(hù)名、密碼等)作為參數(shù)
database.open("database_file");
close()
關(guān)閉數(shù)據(jù)庫(kù)連接。釋放所有資源
database.close();
is_open()(檢查數(shù)據(jù)庫(kù)是否已經(jīng)打開(kāi))
if (database.is_open()) {// 執(zhí)行數(shù)據(jù)庫(kù)操作
}
?事務(wù)管理接口
begin()
database.begin();
commit()
提交事務(wù),確保事務(wù)中的所有操作被永久保存到數(shù)據(jù)庫(kù)中
database.commit();
rollback()
回滾事務(wù),撤銷(xiāo)事務(wù)中的所有操作
database.rollback();
is_transaction_active()
檢查是否存在活動(dòng)的事務(wù)
if (database.is_transaction_active()) {// 處理事務(wù)
}
對(duì)象存取接口
?store()
將一個(gè)對(duì)象持久化到數(shù)據(jù)庫(kù)中。如果對(duì)象已經(jīng)存在,它會(huì)更新對(duì)象;如果對(duì)象是新對(duì)象,它會(huì)插入一條新的記錄
database.store(myObject);
?erase()
從數(shù)據(jù)庫(kù)中刪除一個(gè)對(duì)象
database.erase(myObject);
?load()
從數(shù)據(jù)庫(kù)中加載一個(gè)對(duì)象。通常需要一個(gè)對(duì)象的標(biāo)識(shí)符(如ID)來(lái)查找該對(duì)象
MyObject* obj = database.load<MyObject>(object_id);
?find()
根據(jù)條件查詢(xún)數(shù)據(jù)庫(kù)中的對(duì)象。這個(gè)接口通常支持各種查詢(xún)條件
std::vector<MyObject> objects = database.find<MyObject>("age > 30");
對(duì)象查詢(xún)接口
?query()
執(zhí)行一個(gè)查詢(xún),返回符合條件的對(duì)象列表
auto results = database.query<MyObject>("SELECT * FROM MyObject WHERE age > 30");
count()
返回符合某個(gè)條件的對(duì)象數(shù)量
int count = database.count<MyObject>("age > 30");
?distinct()
查詢(xún)數(shù)據(jù)庫(kù)中某個(gè)字段的不同值
auto distinctNames = database.distinct<MyObject>("name");
類(lèi)型映射與元數(shù)據(jù)接口
?get_type_info()
獲取與某個(gè)對(duì)象類(lèi)型(類(lèi))相關(guān)的元數(shù)據(jù),包括字段、類(lèi)型等
TypeInfo info = database.get_type_info<MyObject>();
?get_object_count()
獲取某個(gè)對(duì)象類(lèi)型在數(shù)據(jù)庫(kù)中的數(shù)量
int objectCount = database.get_object_count<MyObject>();
數(shù)據(jù)庫(kù)備份與恢復(fù)
backup()
執(zhí)行數(shù)據(jù)庫(kù)的備份操作,將數(shù)據(jù)庫(kù)內(nèi)容復(fù)制到一個(gè)備份文件
database.backup("backup_file");
restore()
從備份文件恢復(fù)數(shù)據(jù)庫(kù)
database.restore("backup_file");
基本使用
操作流程總結(jié)
- 構(gòu)建連接池多對(duì)象
- 構(gòu)建數(shù)據(jù)庫(kù)操作database對(duì)象
- 獲取事務(wù)對(duì)象然后開(kāi)啟事務(wù)
- 數(shù)據(jù)庫(kù)操作
- 提交事務(wù)
創(chuàng)建student.hxx
#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 autounsigned long _id;#pragma db uniqueunsigned long _sn;std::string _name;odb::nullable<unsigned short> _age;#pragma db indexunsigned 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 autounsigned long _id;std::string _name;
};//查詢(xún)所有的學(xué)生信息,并顯示班級(jí)名稱(chēng)
#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;
};// 只查詢(xún)學(xué)生姓名 , (?) 外部調(diào)用時(shí)傳入的過(guò)濾條件
#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// 執(zhí)行SQL文件
mysql -u <username> -p TestDB < student.sql
插入操作
void insert_classes(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)odb::transaction trans(db.begin());Classes c1("一年級(jí)一班");Classes c2("一年級(jí)二班");db.persist(c1);db.persist(c2);//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "插入數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}
void insert_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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);//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "插入學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}
查詢(xún)數(shù)據(jù)
通過(guò)學(xué)生表查找某個(gè)學(xué)生的信息
Student select_student(odb::mysql::database &db)
{Student res;try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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 << "數(shù)據(jù)量不對(duì)!\n";return Student();}res = *r.begin();//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "更新學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}return res;
}
更新學(xué)生記錄
通過(guò)update()方法更新學(xué)生記錄,stu是一個(gè)已經(jīng)存在的學(xué)生對(duì)象,更新數(shù)據(jù)會(huì)覆蓋原記錄
void update_student(odb::mysql::database &db, Student &stu)
{try{odb::transaction trans(db.begin());db.update(stu);trans.commit();}catch(std::exception &e){std::cout<<"更新學(xué)生數(shù)據(jù)出錯(cuò):"<<e.what()<<std::endl;}
}
刪除某個(gè)ID的學(xué)生
// 刪除classe_id==2的學(xué)生
void remove_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)odb::transaction trans(db.begin());typedef odb::query<Student> query;db.erase_query<Student>(query::classes_id == 2);//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "更新學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}
查找符合條件學(xué)生的所有信息
void classes_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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>(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. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "更新學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}
查找student表中id == 1的學(xué)生姓名
// 查詢(xún) Student 表中 id == 1 的學(xué)生姓名
void all_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "查詢(xún)所有學(xué)生姓名數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}
代碼綜合測(cè)試
?
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include "student.hxx"
#include "student-odb.hxx"
#include <gflags/gflags.h>DEFINE_string(host, "127.0.0.1", "這是Mysql服務(wù)器地址");
DEFINE_int32(port, 0, "這是Mysql服務(wù)器端口");
DEFINE_string(db, "TestDB", "數(shù)據(jù)庫(kù)默認(rèn)庫(kù)名稱(chēng)");
DEFINE_string(user, "root", "這是Mysql用戶(hù)名");
DEFINE_string(pswd, "123456", "這是Mysql密碼");
DEFINE_string(cset, "utf8", "這是Mysql客戶(hù)端字符集");
DEFINE_int32(max_pool, 3, "這是Mysql連接池最大連接數(shù)量");void insert_classes(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)odb::transaction trans(db.begin());Classes c1("一年級(jí)一班");Classes c2("一年級(jí)二班");db.persist(c1);db.persist(c2);//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "插入數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}void insert_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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);//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "插入學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}Student select_student(odb::mysql::database &db)
{Student res;try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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 << "數(shù)據(jù)量不對(duì)!\n";return Student();}res = *r.begin();//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "更新學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}return res;
}void update_student(odb::mysql::database &db, Student &stu)
{try{odb::transaction trans(db.begin());db.update(stu);trans.commit();}catch(std::exception &e){std::cout<<"更新學(xué)生數(shù)據(jù)出錯(cuò):"<<e.what()<<std::endl;}
}// 刪除classe_id==2的學(xué)生
void remove_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)odb::transaction trans(db.begin());typedef odb::query<Student> query;db.erase_query<Student>(query::classes_id == 2);//5. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "更新學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}//查詢(xún)某個(gè)班級(jí)所有的學(xué)生
void classes_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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>(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. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "更新學(xué)生數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}// 查詢(xún) Student 表中 id == 1 的學(xué)生姓名
void all_student(odb::mysql::database &db)
{try {//獲取事務(wù)對(duì)象開(kāi)啟事務(wù)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. 提交事務(wù)trans.commit();}catch (std::exception &e) {std::cout << "查詢(xún)所有學(xué)生姓名數(shù)據(jù)出錯(cuò):" << e.what() << std::endl;}
}int main(int argc , char *argv[])
{google::ParseCommandLineFlags(&argc, &argv, true);//1. 構(gòu)造連接池工廠配置對(duì)象std::unique_ptr<odb::mysql::connection_pool_factory> cpf(new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));//2. 構(gòu)建數(shù)據(jù)庫(kù)操作對(duì)象odb::mysql::database db(FLAGS_user, FLAGS_pswd, FLAGS_db,FLAGS_host, FLAGS_port, "", FLAGS_cset,0, std::move(cpf));// 插入數(shù)據(jù)insert_classes(db);insert_student(db);// 查詢(xún)數(shù)據(jù)auto 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;//更新數(shù)據(jù)stu.age(15);update_student(db, stu);remove_student(db);classes_student(db);all_student(db);return 0;
}