首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL C++ 封裝實戰:基於 C API 的輕量級面向對象封裝

     編輯:MySQL 綜合教學

背景與選型

項目從 SQL Server 遷移至 MySQL,原使用 ADO 連接。MySQL 官方提供兩種 C++ 介面:

  • MySQL Connector/C++:Sun/Oracle 開發,實現 JDBC 4.0 規範,API 風格偏 Java,熟悉 JDBC 的團隊上手快。
  • MySQL++:基於 STL 封裝 C API,容器化操作風格,原生 C++ 體驗佳。

為快速搭建原型,團隊選擇直接封裝 C API,輕量、可控、無第三方依賴,暫不實現連接池與事務管理。

MySQL C API 核心結構體

  • MYSQL:連接句柄,必須先 mysql_init() 初始化。
  • MYSQL_RES:結果集指針,mysql_store_result() / mysql_use_result() 獲取。
  • MYSQL_ROW:行數據指針數組,mysql_fetch_row() 迭代。
  • MYSQL_FIELD:列元數據(名稱、類型、長度等)。

封裝類設計:MySQLInterface

#ifndef __MYSQL_INTERFACE_H__
#define __MYSQL_INTERFACE_H__

#include 
#include 
#include 
#include 
#include 

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "libmysql.lib")

using namespace std;

class MySQLInterface {
public:
    MySQLInterface();
    virtual ~MySQLInterface();

    // 連接管理
    bool connectMySQL(const char* server, const char* user, const char* pass,
                      const char* db, int port);
    void closeMySQL();

    // 庫/表操作
    bool createDatabase(string& dbname);
    bool createTable(const string& ddl_sql);

    // 數據操作
    bool executeUpdate(const string& sql);           // INSERT/UPDATE/DELETE/DDL
    bool executeQuery(const string& sql,             // SELECT
                      vector>& data); // 返回二維字串表

    // 錯誤信息
    int getErrorNo() const { return errorNum; }
    const char* getErrorMsg() const { return errorInfo; }

private:
    void handleError();

    MYSQL mysqlInstance_;       // 連接對象
    MYSQL_RES* result_ = nullptr; // 結果集
    int errorNum = 0;
    const char* errorInfo = "ok";
};
#endif

關鍵方法實現精要

構造函數:初始化庫與字符集

MySQLInterface::MySQLInterface() {
    mysql_library_init(0, NULL, NULL);
    mysql_init(&mysqlInstance_);
    mysql_options(&mysqlInstance_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); // 或 gbk
}

連接:mysql_real_connect

bool MySQLInterface::connectMySQL(const char* server, const char* user,
                                  const char* pass, const char* db, int port) {
    if (mysql_real_connect(&mysqlInstance_, server, user, pass, db, port, NULL, 0))
        return true;
    handleError();
    return false;
}

建庫並切換

bool MySQLInterface::createDatabase(string& dbname) {
    string sql = "CREATE DATABASE IF NOT EXISTS " + dbname;
    if (mysql_query(&mysqlInstance_, sql.c_str())) { handleError(); return false; }
    sql = "USE " + dbname;
    if (mysql_query(&mysqlInstance_, sql.c_str())) { handleError(); return false; }
    return true;
}

執行更新(DDL/DML)

bool MySQLInterface::executeUpdate(const string& sql) {
    if (mysql_query(&mysqlInstance_, sql.c_str()) == 0)
        return true;
    handleError();
    return false;
}

執行查詢並轉換為 vector<vector<string>>

bool MySQLInterface::executeQuery(const string& sql,
                                  vector>& data) {
    if (mysql_query(&mysqlInstance_, sql.c_str())) {
        handleError();
        return false;
    }
    result_ = mysql_store_result(&mysqlInstance_);
    if (!result_) { handleError(); return false; }

    int fields = mysql_num_fields(result_);
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(result_))) {
        vector record;
        record.reserve(fields);
        for (int i = 0; i < fields; ++i) {
            record.emplace_back(row[i] ? row[i] : "");
        }
        data.emplace_back(std::move(record));
    }
    mysql_free_result(result_);
    result_ = nullptr;
    return true;
}

錯誤處理與資源釋放

void MySQLInterface::handleError() {
    errorNum = mysql_errno(&mysqlInstance_);
    errorInfo = mysql_error(&mysqlInstance_);
}

void MySQLInterface::closeMySQL() {
    if (result_) { mysql_free_result(result_); result_ = nullptr; }
    mysql_close(&mysqlInstance_);
    mysql_library_end();
}

使用示例

int main() {
    MySQLInterface db;
    if (!db.connectMySQL("127.0.0.1", "root", "password", "test_db", 3306)) {
        cerr << "Connect failed: " << db.getErrorMsg() << endl;
        return 1;
    }

    // 建表
    db.executeUpdate("CREATE TABLE IF NOT EXISTS t_user("
                     "id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,"
                     "name VARCHAR(50) NOT NULL,"
                     "age TINYINT UNSIGNED NOT NULL DEFAULT 0)");

    // 寫入
    db.executeUpdate("INSERT INTO t_user(name,age) VALUES('Alice',25),('Bob',30)");

    // 查詢
    vector> rows;
    if (db.executeQuery("SELECT id,name,age FROM t_user", rows)) {
        for (auto& r : rows) {
            cout << "ID:" << r[0] << " Name:" << r[1] << " Age:" << r[2] << endl;
        }
    }

    db.closeMySQL();
    return 0;
}

後續擴展方向

  1. 連接池:使用 std::queue<MYSQL*> + std::mutex + std::condition_variable 實現線程安全池。
  2. 事務支援:封裝 BEGIN/COMMIT/ROLLBACK,提供 RAII 風格 TransactionGuard。
  3. 預處理語句:使用 MYSQL_STMT、MYSQL_BIND 防注入、提升重複執行效能。
  4. 異步/非阻塞:配合 mysql_real_connect_nonblocking、mysql_send_query 實現高併發。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved