本地緩存(key-value)

目前在做本地緩存時常用的方式是用sqlite作爲本地緩存數據庫,緩存使用的場景很多,每次都設計表就變成一件很麻煩的事情,而且很多場景就只是用來記錄一些配置信息,所以採用key-value這種接口去封裝sqlite就是一種很好的方式。

接口:

#include <string>

class LocalStorage
{
public:
	SINGLETON_DEFINE(LocalStorage);
	LocalStorage();
	~LocalStorage();

public:
	bool Load(std::string sBusiness, std::string key, __int32& value);
	bool Load(std::string sBusiness, std::string key, __int64& value);
	bool Load(std::string sBusiness, std::string key, std::string& value);
	bool Load(std::string sBusiness, std::vector<std::pair<std::string, std::string>>& keyValue);

	bool Save(std::string sBusiness, std::string key, __int32 value);
	bool Save(std::string sBusiness, std::string key, __int64 value);
	bool Save(std::string sBusiness, std::string key, std::string value);

	bool Remove(std::string sBusiness, std::string key);
	bool Remove(std::string sBusiness);
};

load方法共有4個重載方法1,2這兩個數值型底層調用的還是第三個string型的方法,後面只是將string轉爲了數值型。

load的第四個方法是將整個業務的所有key-value取出。

Save共三個方法,1,2的數值型接口底層也是調用的第三個string型的。

Remove兩個方法,第一個將對應key的key-value記錄刪除,第二個刪除整個業務緩存。

第一個參數業務內部對應的是一張表,key-value對應表中的記錄。每一條記錄都是固定的key-value格式。

實現:

#include "localstorage.h"
#include "db/db_sqlite3.h"
#include "base/sqllite/db_sqlite3.h"
#include <ShlObj.h>
#include <Shlwapi.h>

namespace{
	ndb::SQLiteDB   db_;
	bool OpenDB()
	{
		char szPath[MAX_PATH] = { 0 };
		::SHGetSpecialFolderPathA(nullptr, szPath, CSIDL_LOCAL_APPDATA, FALSE);
		::PathAppendA(szPath, "localstorage.db");
		bool result = db_.Open(szPath,
			"",
			ndb::SQLiteDB::modeReadWrite | ndb::SQLiteDB::modeCreate | ndb::SQLiteDB::modeSerialized
			);
		return result;
	}
	bool CloseDB()
	{
		return db_.Close();
	}

	bool CreateTable(std::string sBusiness)
	{
		std::string sSqlCreate = "CREATE TABLE IF NOT EXISTS ";
		sSqlCreate += sBusiness;
		sSqlCreate += "(key TEXT PRIMARY KEY, value TEXT)";

		int dbresult = SQLITE_OK;
		dbresult |= db_.Query(sSqlCreate.c_str());
		bool no_error = dbresult == SQLITE_OK;
		return no_error;
	}
}


LocalStorage::LocalStorage()
{
	OpenDB();
}


LocalStorage::~LocalStorage()
{
	CloseDB();
}

bool LocalStorage::Load(std::string sBusiness, std::string key, __int32& value)
{
	std::string sValue;
	if (Load(sBusiness, key, sValue))
	{
		value = std::stoi(sValue);
	}
	return true;
}

bool LocalStorage::Load(std::string sBusiness, std::string key, __int64& value)
{
	std::string sValue;
	if (Load(sBusiness, key, sValue))
	{
		value = std::stoll(sValue);
	}
	return true;
}

bool LocalStorage::Load(std::string sBusiness, std::string key, std::string& value)
{
	ndb::SQLiteStatement stmt;
	std::string sSqlSelect = "SELECT * FROM ";
	sSqlSelect += sBusiness;
	sSqlSelect += " WHERE key=?;";
	db_.Query(stmt, sSqlSelect.c_str());
	stmt.BindText(1, key.c_str(), key.size());
	int32_t result = stmt.NextRow();
	if (result == SQLITE_ROW)
	{
		value = stmt.GetTextField(1);
		return true;
	}
	return false;
}

bool LocalStorage::Load(std::string sBusiness, std::vector<std::pair<std::string, std::string>>& keyValue)
{
	ndb::SQLiteStatement stmt;
	std::string sSqlSelect = "SELECT * FROM ";
	sSqlSelect += sBusiness;
	sSqlSelect += ";";
	int result = SQLITE_OK;
	result |= db_.Query(stmt, sSqlSelect.c_str());

	if (SQLITE_OK == result)
	{
		result = stmt.NextRow();
		while (result == SQLITE_ROW)
		{
			const char* sKey = stmt.GetTextField(0);
			const char* sValue = stmt.GetTextField(1);
			if (nullptr != sKey && nullptr != sValue)
			{
				keyValue.push_back(std::make_pair(sKey, sValue));
			}
			result = stmt.NextRow();
		}
		return true;
	}
	return false;
}

bool LocalStorage::Save(std::string sBusiness, std::string key, __int32 value)
{
	std::string sValue = std::to_string(value);
	return Save(sBusiness, key, sValue);
}

bool LocalStorage::Save(std::string sBusiness, std::string key, __int64 value)
{
	std::string sValue = std::to_string(value);
	return Save(sBusiness, key, sValue);
}

bool LocalStorage::Save(std::string sBusiness, std::string key, std::string value)
{
	if (CreateTable(sBusiness))
	{
		std::string sSqlInsert = "INSERT OR REPLACE into ";
		sSqlInsert += sBusiness;
		sSqlInsert += " (key,value) values (?,?);";
		ndb::SQLiteStatement stmt;
		db_.Query(stmt, sSqlInsert.c_str());
		stmt.BindText(1, key.c_str(), key.size());
		stmt.BindText(2, value.c_str(), value.size());
		int32_t result = stmt.NextRow();
		bool no_error = result == SQLITE_OK || result == SQLITE_ROW || result == SQLITE_DONE;
		if (no_error)
		{
			return true;
		}
	}

	return false;
}

bool LocalStorage::Remove(std::string sBusiness, std::string key)
{
	std::string sSqlDeleteRecord = "DELETE FROM ";
	sSqlDeleteRecord += sBusiness;
	sSqlDeleteRecord += " WHERE key=?;";
	ndb::SQLiteStatement stmt;
	int dbresult = SQLITE_OK;
	dbresult |= db_.Query(stmt, sSqlDeleteRecord.c_str());
	stmt.BindText(1, key.c_str());
	int32_t result = stmt.NextRow();
	return (result == SQLITE_OK || result == SQLITE_ROW || result == SQLITE_DONE);
}

bool LocalStorage::Remove(std::string sBusiness)
{
	std::string sSqlDropTable = "DROP TABLE ";
	sSqlDropTable += sBusiness;
	sSqlDropTable += ";";

	int dbresult = SQLITE_OK;
	dbresult |= db_.Query(sSqlDropTable.c_str());
	return dbresult == SQLITE_OK;
}

 

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