C++ 通用數據庫操作之SOCI

簡介

SOCI是用C ++編寫的數據庫訪問庫,使人將SQL查詢嵌入常規C ++代碼中,而完全位於標準C ++中。

這個想法是爲C ++程序員提供一種以最自然,最直觀的方式訪問SQL數據庫的方法。如果您發現現有庫太難滿足您的需求或分散注意力,那麼SOCI可能是一個不錯的選擇。

當前支持的後端:

一、連接測試

#include <iostream>
#include <exception>
#include <soci/soci.h>
#include <soci/mysql/soci-mysql.h>

void connectTest()
{
     try
    {
        soci::session sql(soci::mysql, "host=127.0.0.1 dbname=mydb user=root password='123456'");
        
        soci::rowset<soci::row> rs = (sql.prepare << "select Id, username,age FROM student");
        for (auto it = rs.begin(); it != rs.end(); ++it)
        {
            const soci::row& row = *it;
            std::cout << "id:" << row.get<uint>("Id")  << " username:" << row.get<std::string>("username")
                << " age:" << row.get<int>("age") << std::endl;
        }
    }
    catch(soci::soci_error & e)
    {
        std::cout << e.what() << std::endl;
    }
}

二、查詢

1、單行查詢
 
soci::row itRet;
(sqlSession << strSql),into(itRet);
if (!sqlSession.got_data())
    return;
auto val = itRet.get<std::string>(0);

2、多行查詢

soci::rowset<soci::row> rslt = (sqlSession.prepare << strSql);
for (auto& itRet : rslt)
{
}

3、多行查詢存放到列表

void queryTest()
{
     try
    {
       soci::session sqlSession(soci::mysql, "host=127.0.0.1 dbname=mydb user=root password='123456'");     
       std::vector<std::string> vecStudent(100);
       std::vector<int> vecAge(100);
       sqlSession << "select username,age FROM student", soci::into(vecStudent), soci::into(vecAge);
     
    }
    catch(soci::soci_error & e)
    {
        std::cout << e.what() << std::endl;
    }
}

4、多行全表數據查詢

    
soci::row itRet;
soci::statement st = ((sqlSession.prepare <<  strSQL),soci::into(itRet));
st.execute();

//獲取字段信息
std::vector<std::string> vecFieldList;
for (std::size_t i = 0; i != itRet.size(); ++i)
{
     const soci::column_properties & props =  itRet.get_properties(i);
     std::string strField = props.get_name();
     vecFieldList.push_back(strField);
}

while (st.fetch())
{
    for (auto i = 0; i < itRet.size(); i++)
    {
        std::string strValue = GetFieldValue(itRet, i);
    }
}

三、更新、插入、刪除

1、簡易操作
auto username = "admin";
auto age = 10;
sqlSession << "insert into student(username, age) values(:username, :age)", use(username), use(age);

2、獲取影響行數

statement st = (sqlSession.prepare << "delete from student where id=:id", use(id));
st.execute(true);
int affected_rows = st.get_affected_rows();

四、多線程下連接池

int g_pool_size = 5;
soci::connection_pool g_pool(g_pool_size);
void init_pool()
{
    for (int i = 0; i < g_pool_size; ++i)
    {
        session& sql = g_pool.at(i);
        sql.open(soci::mysql, "host=127.0.0.1 dbname=mydb user=root password='123456'");
    }
}
soci::session sql(g_pool);
sqlSession << "insert into student(username, age) values(:username, :age)", soci::use(username), soci::use(age);

五、泛型加載,統一轉換成字符型

std::string GetFieldValue(const soci::row&  itRet, int pos)
{
       const soci::column_properties & props = itRet.get_properties(pos);
       if (itRet.get_indicator(pos) == soci::i_null)
       {
              return "";
       }
       switch (props.get_data_type())
       {
       case soci::dt_string:
              return itRet.get<std::string>(pos);
              break;
       case soci::dt_double:
              return std::to_string(itRet.get<double>(pos));
              break;
       case soci::dt_integer:
              return std::to_string(itRet.get<int>(pos));
              break;
       case soci::dt_long_long:
              return std::to_string(itRet.get<long long>(pos));
              break;
       case soci::dt_unsigned_long_long:
              return std::to_string(itRet.get<unsigned long long>(pos));
              break;
       case soci::dt_date:
              std::tm when = itRet.get<std::tm>(pos);
              return asctime(&when);
              break;
       }
       return std::string();
}

soci::rowset<soci::row> rs = (sqlSession.prepare << "select Id, username,age FROM student");
for (auto& it : rs)
{
    std::cout << "username:" << GetFieldValue(it, 0)  << " age:" << GetFieldValue(it, 1) << std::endl;
}
 

六、簡化數據讀取,防止空數據導致異常

 

template<typename T, typename V>
void GetFieldValue(const soci::row&  itRet, T at, V& val)
{
       val = itRet.get<V>(at, val);
}
template<typename V>
void GetFieldValue(const soci::row&  itRet, int pos, V& val)
{
       val = itRet.get<V>(pos, val);
}
template<typename V>
void GetFieldValue(const soci::row&  itRet, const char* field, V& val)
{
       val = itRet.get<V>(field, val);
}

soci::rowset<soci::row> rs = (sqlSession.prepare << "select Id, username,age FROM student");
for (auto& it : rs)
{
    std::stirng name;
    int age = -1;
    GetFieldValue(it, 0, name);
    GetFieldValue(it, 1, age);
    std::cout << "username:" <<  name << " age:" << age << std::endl;
}

七、ORM

struct Person
{
    int id;
    std::string firstName;
    std::string lastName;
    std::string gender;
};


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.firstName = v.get<std::string>("FIRST_NAME");
            p.lastName = v.get<std::string>("LAST_NAME");


            // p.gender will be set to the default value "unknown"
            // when the column is null:
            p.gender = v.get<std::string>("GENDER", "unknown");


            // alternatively, the indicator can be tested directly:
            // if (v.indicator("GENDER") == i_null)
            // {
            //     p.gender = "unknown";
            // }
            // else
            // {
            //     p.gender = v.get<std::string>("GENDER");
            // }
        }


        static void to_base(const Person & p, values & v, indicator & ind)
        {
            v.set("ID", p.id);
            v.set("FIRST_NAME", p.firstName);
            v.set("LAST_NAME", p.lastName);
            v.set("GENDER", p.gender, p.gender.empty() ? i_null : i_ok);
            ind = i_ok;
        }
    };
}
session sql(oracle, "service=db1 user=scott password=tiger");

Person p;
p.id = 1;
p.lastName = "Smith";
p.firstName = "Pat";
sql << "insert into person(id, first_name, last_name) "
        "values(:ID, :FIRST_NAME, :LAST_NAME)", use(p);

Person p1;
sql << "select * from person", into(p1);
assert(p1.id == 1);
assert(p1.firstName + p.lastName == "PatSmith");
assert(p1.gender == "unknown");

p.firstName = "Patricia";
sql << "update person set first_name = :FIRST_NAME "
        "where id = :ID", use(p);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章