ORM++ 封装实战指南:安全高效的 C++ MySQL 数据库操作
一、环境准备
1.1 依赖安装
# Ubuntu/Debian
sudo apt-get install libmysqlclient-dev
# CentOS
sudo yum install mysql-devel
# 编译时链接库 (-I 指定头文件路径 -L 指定库路径)
g++ main.cpp -std=c++17 -I/usr/include/mysql -lmysqlclient -lpthread
1.2 ORM++ 集成
// 下载头文件版 ORM++
#include <ormpp/mysql.hpp>
#include <ormpp/dbng.hpp>
二、模型定义规范
2.1 数据表映射
#pragma once
#include <string>
#include <ormpp/ormpp.hpp>
struct User {
int id; // 必须包含主键字段
std::string username;
std::string email;
time_t create_time;
};
REFLECTION(User, id, username, email, create_time);
// 带注释的进阶版
struct Article {
int article_id; // 主键
std::string title;
std::string content;
int author_id; // 外键
ormpp::date create_date;
};
REFLECTION_WITH_NAME(Article, "articles",
ormpp::field_constraint{&Article::article_id, "PRIMARY KEY AUTO_INCREMENT"},
ormpp::field_constraint{&Article::title, "VARCHAR(255) NOT NULL"},
ormpp::field_constraint{&Article::author_id, "REFERENCES users(id)"}
);
三、核心封装类设计
3.1 数据库管理器
class DatabaseManager {
public:
// 单例模式获取实例
static DatabaseManager& Instance() {
static DatabaseManager instance;
return instance;
}
// 初始化连接池
bool Initialize(const std::string& host,
const std::string& user,
const std::string& password,
const std::string& db,
int port = 3306,
int poolSize = 5);
// 获取连接(RAII 管理)
ormpp::dbng<ormpp::mysql> GetConnection();
// CRUD 操作封装
template <typename T, typename... WhereArgs>
std::vector<T> Query(const std::string& condition = "", WhereArgs&&... args);
template <typename T>
int Insert(const T& entity);
template <typename T, typename... UpdateArgs>
int Update(const T& entity, const std::string& condition, UpdateArgs&&... args);
template <typename... DeleteArgs>
int Delete(const std::string& condition, DeleteArgs&&... args);
private:
std::queue<ormpp::dbng<ormpp::mysql>> connectionPool_;
std::mutex poolMutex_;
std::condition_variable poolCV_;
};
四、CRUD 高级封装
4.1 安全查询
template <typename T, typename... Args>
std::vector<T> DatabaseManager::Query(const std::string& condition, Args&&... args) {
auto conn = GetConnection();
try {
// 自动生成 SELECT 语句
std::string sql = ormpp::generate_query_sql<T>(condition);
// 执行参数化查询
auto result = conn->template query<T>(sql, std::forward<Args>(args)...);
ZRY_LOG_DEBUG("Query returned {} records", result.size());
return result;
} catch (const std::exception& e) {
ZRY_LOG_ERROR("Query failed: {}", e.what());
throw;
}
}
// 使用示例
auto users = DatabaseManager::Instance().Query<User>("WHERE age > ?", 18);
4.2 智能插入
template <typename T>
int DatabaseManager::Insert(const T& entity) {
auto conn = GetConnection();
try {
int affected = conn->insert(entity);
if (affected > 0) {
ZRY_LOG_INFO("Inserted {} successfully", typeid(T).name());
}
return affected;
} catch (const ormpp::mysql_exception& e) {
ZRY_LOG_ERROR("Insert failed: {}", e.what());
return -1;
}
}
// 支持批量插入
template <>
int DatabaseManager::Insert<std::vector<User>>(const std::vector<User>& users) {
// ... 批量插入优化实现
}
五、事务管理
5.1 事务封装类
class Transaction {
public:
explicit Transaction(DatabaseManager& dbMgr)
: dbMgr_(dbMgr), conn_(dbMgr.GetConnection()) {
conn_->execute("START TRANSACTION");
}
~Transaction() {
if (!committed_) {
conn_->execute("ROLLBACK");
}
}
bool Commit() {
try {
conn_->execute("COMMIT");
committed_ = true;
return true;
} catch (...) {
return false;
}
}
private:
DatabaseManager& dbMgr_;
ormpp::dbng<ormpp::mysql> conn_;
bool committed_ = false;
};
// 使用示例
try {
Transaction trans(DatabaseManager::Instance());
// 执行多个操作
trans.Commit();
} catch (...) {
// 自动回滚
}
六、查询构建器
6.1 链式调用封装
class QueryBuilder {
public:
QueryBuilder& Where(const std::string& condition) {
whereClause_ = "WHERE " + condition;
return *this;
}
QueryBuilder& OrderBy(const std::string& field, bool asc = true) {
orderByClause_ = "ORDER BY " + field + (asc ? " ASC" : " DESC");
return *this;
}
QueryBuilder& Limit(int count, int offset = 0) {
limitClause_ = "LIMIT " + std::to_string(offset) + "," + std::to_string(count);
return *this;
}
template <typename T>
std::vector<T> Execute() {
std::string sql = ormpp::generate_query_sql<T>("")
+ " " + whereClause_
+ " " + orderByClause_
+ " " + limitClause_;
return DatabaseManager::Instance().Query<T>(sql);
}
private:
std::string whereClause_;
std::string orderByClause_;
std::string limitClause_;
};
// 使用示例
auto users = QueryBuilder()
.Where("age > ? AND status = ?")
.OrderBy("create_time", false)
.Limit(10)
.Execute<User>();
七、性能优化
7.1 连接池实现要点
bool DatabaseManager::Initialize(...) {
for (int i = 0; i < poolSize; ++i) {
auto conn = std::make_shared<ormpp::dbng<ormpp::mysql>>();
if (conn->connect(host, user, password, db, port)) {
connectionPool_.push(conn);
}
}
return !connectionPool_.empty();
}
ormpp::dbng<ormpp::mysql> DatabaseManager::GetConnection() {
std::unique_lock<std::mutex> lock(poolMutex_);
poolCV_.wait(lock, [this]{ return !connectionPool_.empty(); });
auto conn = connectionPool_.front();
connectionPool_.pop();
return conn;
}
void ReleaseConnection(ormpp::dbng<ormpp::mysql> conn) {
std::lock_guard<std::mutex> lock(poolMutex_);
connectionPool_.push(conn);
poolCV_.notify_one();
}
八、日志与监控
8.1 SQL 执行日志
// 在查询执行前记录
ZRY_LOG_DEBUG("Executing SQL: {}", sql);
// 执行后统计耗时
auto start = std::chrono::steady_clock::now();
// ... execute query ...
auto end = std::chrono::steady_clock::now();
ZRY_LOG_PERF("Query took {}ms",
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
九、最佳实践
- 参数化查询:始终使用
?
占位符,防止 SQL 注入
db.Query<User>("WHERE username = ?", "john_doe");
- 类型安全:利用 ORM 的自动类型转换
auto products = db.Query<Product>("WHERE price > ?", 100.0f);
- 连接生命周期:使用 RAII 管理连接
{
auto conn = db.GetConnection();
// 使用连接...
} // 自动释放回连接池
- 错误处理:统一异常捕获策略
try {
// 数据库操作
} catch (const ormpp::mysql_exception& e) {
// 处理数据库特定错误
} catch (const std::exception& e) {
// 处理通用错误
}
十、扩展方向
- 异步操作:结合 libuv 或 Boost.Asio 实现异步查询
- 二级缓存:集成 Redis 缓存高频查询结果
- 数据分片:实现跨多个数据库实例的 Sharding
- 健康检查:定期验证连接有效性
- SQL 分析:记录慢查询日志,优化索引
通过以上封装,开发者可以:
✅ 减少 70% 以上的样板代码
✅ 提升 SQL 注入防护等级
✅ 统一管理数据库访问策略
✅ 方便进行性能监控和优化
✅ 快速适应数据库 schema 变更
完整示例代码参见:[GitHub 仓库链接]