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

C++ 輕量級 MySQL 訪問庫 SOCI 實戰入門:從安裝到 ORM 映射

     編輯:MySQL 綜合教學

C++ 輕量級 MySQL 訪問庫 SOCI 實戰入門:從安裝到 ORM 映射

在 C++ 中操作 MySQL 一直缺乏像 Java Hibernate 或 Python SQLAlchemy 這樣成熟的 ORM 框架。SOCI (The C++ Database Access Library) 提供了簡潔的類 SQL 語法、參數綁定與行到結構體的自動映射,且依賴輕、編譯快,是 C++ 專案接入 MySQL 的優選。本文通過完整單元測試代碼演示核心用法。

環境準備

-- 建庫建表
CREATE DATABASE soci;
USE soci;
CREATE TABLE tb_test (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(32) DEFAULT '',
  sex INT(11) DEFAULT 0,
  PRIMARY KEY (id),
  UNIQUE KEY name (name)
);

核心 API 速覽

  • session sql(backend, conn_str):建立連接,MySQL 後端為 mysql。
  • sql << "SQL" [, into(...), use(...)]:流式綁定輸出/輸入參數。
  • indicator:指示查詢結果狀態(i_ok、i_null、i_truncated)。
  • type_conversion<T>:自定義結構體與表列的雙向映射。

基本查詢:單行 / 多行

1. 單行查詢

TEST(soci, select_one) {
  try {
    session sql(mysql, "host=localhost db=soci user=dantezhu");
    indicator ind;
    string name = "dandan";
    int sex;
    sql << "SELECT sex FROM tb_test WHERE name = :name", into(sex, ind), use(name);
    ASSERT_EQ(ind, i_ok) << name;
  } catch (exception const &e) { FAIL() << e.what(); }
}

into(sex, ind) 接收結果,use(name) 綁定輸入參數。成功時 ind == i_ok。

2. 多行查詢(向量綁定)

TEST(soci, select_multi) {
  session sql(mysql, "db=soci user=dantezhu");
  indicator ind;
  int count;
  sql << "SELECT COUNT(*) FROM tb_test", into(count, ind);
  if (count == 0) return;
  int sex = 1;
  vector<string> vec_name(count);
  vector<int> vec_sex(count);
  sql << "SELECT name, sex FROM tb_test WHERE sex = :sex", into(vec_name), into(vec_sex), use(sex);
}

多行時 into() 參數為 vector,需預先分配大小。

寫操作:INSERT / UPDATE / DELETE

TEST(soci, insert) {
  session sql(mysql, "db=soci user=dantezhu");
  string name = "dandan"; int sex = 1;
  sql << "INSERT INTO tb_test(name, sex) VALUES(:name, :sex)", use(name), use(sex);
}

已知限制:SOCI 目前無法直接返回 affected_rows 或自增主鍵值,需額外查詢 LAST_INSERT_ID()。

進階:結構體與表的雙向映射 (ORM)

1. 定義結構體並特化 type_conversion

struct Person {
  int id;
  std::string name;
  int sex;
};

namespace soci {
template<>
struct type_conversion<Person> {
  typedef values base_type;
  static void from_base(values const &v, indicator /*ind*/, Person &p) {
    p.id   = v.get<int>("id");
    p.name = v.get<std::string>("name");
    p.sex  = v.get<int>("sex");
  }
  static void to_base(const Person &p, values &v, indicator &ind) {
    v.set("id", p.id);
    v.set("name", p.name);
    v.set("sex", p.sex);
    ind = i_ok;
  }
};
}

注意:官方文檔範例中模板特化語法有誤,需按上述寫法。

2. 結構體查詢

TEST(soci, select_obj) {
  session sql(mysql, "db=soci user=dantezhu");
  string name = "dandan";
  Person p;
  sql << "SELECT id, name, sex FROM tb_test WHERE name = :name", into(p), use(name);
  if (sql.got_data()) cout << p.id << "," << p.name << "," << p.sex << endl;
}

3. 結構體寫入

TEST(soci, insert_obj) {
  session sql(mysql, "db=soci user=dantezhu");
  Person p = {0, "niuniu", 2};
  sql << "INSERT INTO tb_test(name, sex) VALUES(:name, :sex)", use(p);
}

自動展開結構體成員為參數,極大簡化代碼。

總結與資源

  • SOCI 輕量、無侵入、支持多後端,適合追求現代 C++ 風格的項目。
  • 完整測試代碼下載:vimercode/soci_test
  • 若需更豐富的 ORM 功能(關聯、延遲加載),可評估 litesql 或 ODB,但編譯依賴更重。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved