程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> (原創)sqlite封裝庫SmartDB1.3發布

(原創)sqlite封裝庫SmartDB1.3發布

編輯:C++入門知識

  最近終於稍微有點空對SmartDB進行升級了,SmartDB1.3比之前的版本做了簡化,增強了易用性和靈活性。
  SmartDB對sqlite做了一層封裝,屏蔽了諸多細節,使得我們使用起來很方便。在注重易用性的基礎上還兼顧了性能和靈活性。

易用性

接口很簡單,基本接口有如下幾個:

void Open(const string& fileName);
bool Close();

//數據庫操作接口
template <typename... Args>
bool Excecute(const string& sqlStr, Args && ... args);

//返回一個值,如執行簡單的匯聚函數
template < typename R = sqlite_int64, typename... Args>
R ExecuteScalar(const string& sqlStr, Args&&... args);

//查詢接口
template <typename... Args>
std::shared_ptr<rapidjson::Document> Query(const string& query, Args&&... args);

//事務
bool Begin();
bool RollBack();
bool Commit();

通過這幾個接口,你就可以做所有的事情了。看一個簡單的例子吧:

void Test()
{
    SmartDB db;
    db.Open("test.db");

    const string sqlcreat = "CREATE TABLE if not exists PersonTable(ID INTEGER NOT NULL, Name Text, Address BLOB);";

    if (!db.Excecute(sqlcreat))
        return;

    const string sqlinsert = "INSERT INTO PersonTable(ID, Name, Address) VALUES(?, ?, ?);";
    int id = 2;
    string name = "Peter";
    string city = "zhuhai";
    blob bl = { city.c_str(), city.length() + 1 };

    if (!db.Excecute(sqlinsert, id, "Peter", nullptr))
        return;
}

上面的例子創建了數據庫和數據表,並插入了一行記錄,都是通過Excecute搞定,是不是很簡單。

靈活性

  對數據庫接口做了增強,使我們可以接收tuple和json,因為有時候我們需要將要保存的值先保存起來,在需要的時候再存到數據庫,這時就需要一個載體來事先保存這些數據,這裡通過json或者tuple是最合適的。來看看tuple和json接口:

template<typename Tuple>
bool ExcecuteTuple(const string& sqlStr, Tuple&& t);

bool ExcecuteJson(const string& sqlStr, const char* json);

和上面的Excecute很相似吧。看看他們的用法:

db.ExcecuteTuple(sqlinsert, std::forward_as_tuple(id, "Peter", bl));

json接口稍微復雜一點,這裡我們用到了rapidjson。它的用法:

void TestJson(SmartDB& db, const string& sqlinsert)
{
    rapidjson::StringBuffer buf;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
    writer.StartArray();
    for (size_t i = 0; i < 10; i++)
    {
        writer.StartObject();
        writer.String("ID");
        writer.Int(i + 1);

        writer.String("Name");
        writer.String("Peter");

        writer.String("Address");
        writer.String("Zhuhai");
        writer.EndObject();
    }
    writer.EndArray();

    auto r = db.ExcecuteJson(sqlinsert, buf.GetString());
}

上面寫json對象有點繁瑣,沒關系,可以通過我封裝的JsonCpp來簡化:

void TestJson(SmartDB& db, const string& sqlinsert)
{
    //這裡通過jsoncpp封裝類來簡化json對象的創建
    JsonCpp jcp;
    jcp.StartArray();
    for (size_t i = 0; i < 10; i++)
    {
        jcp.StartObject();
        jcp.WriteJson("ID", i);
        jcp.WriteJson("Name", "Peter");
        jcp.WriteJson("Address", "zhuhai");
        jcp.EndObject();
    }
    jcp.EndArray();

    auto r = db.ExcecuteJson(sqlinsert, buf.GetString());
}

靈活性

  將查詢結果直接放到json對象中,避免了物理表需要和業務實體一一對應的問題,底層物理表即使修改了,數據庫這層不需要修改,是穩定的,因為查詢的結果是json對象,它本身就是一個自描述的結構體,不關心底層數據表的變化。返回json的另外一個好處是,我可以將json串通過網絡傳輸出去,或者直接傳給其它的語言,因為json是一個標准的格式,所以,不同的語言都能輕松的識別它,它不僅僅是查詢的結果還是一個聯系其它語言或者系統的紐帶,非常靈活。看看它的基本用法:

auto p = db.Query("select * from TestInfoTable");

返回的是一個json對象,要訪問它也很簡單:

rapidjson::Document& doc = *p;
    for (size_t i = 0, len = doc.Size(); i < len; i++)
    {
        for (size_t j = 0, size = doc[i].GetSize(); j < size; ++j)
        {
            //doc[i][j];鍵值對
        }
    }
const char* json = doc.GetString(); //返回json串

性能

啟用事務,插入性能很高,雙核筆記本上插入一個七字段的表能達到二十多萬行每秒的速度。查詢結果的速度也較快,也能達到二十萬行每秒的速度。看看性能測試的代碼:

void TestPerformance()
{
    SmartDB db;
    db.Open("test.db");
    const string sqlcreat = "CREATE TABLE if not exists TestInfoTable(ID INTEGER NOT NULL, KPIID INTEGER, CODE INTEGER, V1 INTEGER, V2 INTEGER, V3 REAL, 

V4 TEXT);";
    if (!db.Excecute(sqlcreat))
        return;

    boost::timer t;
    const string sqlinsert = "INSERT INTO TestInfoTable(ID, KPIID, CODE, V1, V2, V3, V4) VALUES(?, ?, ?, ?, ?, ?, ?);";
    bool ret = db.Prepare(sqlinsert);
    db.Begin();
    for (size_t i = 0; i < 1000000; i++)
    {
        ret = db.ExcecuteArgs(i, i, i, i, i, i + 1.25, "it is a test");
        if (!ret)
            break;
    }

    if (ret)
        db.Commit(); //提交事務
    else
        db.RollBack(); //回滾

    cout << t.elapsed() << endl;
    t.restart();

    auto p = db.Query("select * from TestInfoTable");

    cout << t.elapsed() << endl;
    cout << "size: " << p->Size() << endl;
}

  雙核筆記本上顯示:4.6s和5s。這個性能完全滿足平時的開發。

如果你發現還有比這更簡潔、靈活和高效的sqlite封裝庫請告訴我,如果沒有請點一下推薦,謝謝。^_^

SmartDBV1.03

歡迎使用,如果發現有問題請向我反饋。

c++11 boost技術交流群:296561497,歡迎大家來交流技術。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved