C++ 通用数据库操作之SOCI

Wesley13
• 阅读 1155

简介

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);
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
Linux 下连接sqlserver(下)
基于ODBC开发odbc接口环境部署好后,就可以开始进行开发了,微软官网有详细的接口操作说明,但odbc接口还是太底层,操作起来比较麻烦,这里采用数据库的封装类soci来实现快速开发。soci是一个用C封装的数据库访问库,通过“前端(应用程序)/核心/后端(数据库适配)”模式支持firebird,mysql,sql
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Hibernate纯sql查询结果和该sql在数据库直接查询结果不一致
问题:今天在做一个查询的时候发现一个问题,我先在数据库实现了我需要的sql,然后我在代码中代码:selectdistinctd.id,d.name,COALESCE(c.count_num,0),COALESCE(c.count_fix,0),COALESCE(c
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这