需求:新功能增加,完成软件新界面增加(包含逻辑与数据)
实现:
- 获取数据库内容
- 为接口定义对应的数据格式
- 完成数据结构组成
- 数据获取接口实现
- 数据更改后写入数据库接口实现
获取数据库内容;
- 首先,已经默认拥有了数据库,并内部已有数据;
- 定义数据接口
bool GetLifetime(vector<shared_ptr<LifetimeAddr>>& datas);
这里无法知晓数据大小,采用容器智能指针的方式获取数据,并使用bool返回值确定是否获取成功
- 完成接口内容实现
bool GetLifetime(vector<shared_ptr<LifetimeAddr>>& datas)
{
string sql = "SELECT "
"t1.id, t1.name_id,"
"t1.used, t1.warn, t1.stop,"
"t1.usedAddr, t1.warnAddr, t1.stopAddr,"
"t1.timeReplace, t1.permission "
"FROM t_ui_lifetime t1 "
"ORDER BY t1.id ASC";
SqliteResult result;
int r = execSql(sql, result);
if (r || result.m_vecValues.empty())
return SQL_CODE_2_BOOL(r);
if (!datas.empty())
datas.clear();
/* if (&datas != nullptr)
&datas == NULL;*/
for (size_t i = 0; i < result.m_vecValues.size(); i++)
{
shared_ptr<LifetimeAddr> addr = make_shared<LifetimeAddr>();
_GetLifetimeValue(result, i, addr);
datas.push_back(addr);
}
return SQL_CODE_2_BOOL(r);
}
- 定义string类型变量,接收SQL语句读取出的数据库内容
- FORM t_ui_lifeime ti 表名太长,取别名为 t1;
- ORDER BY t1.id ASC 为id索引
- SqliteResult 为字符串容器类,内部定义两个vetor容器;如图
struct SqliteResult {
vector<string> m_vecIds;
vector<vector<string>> m_vecValues;
};
- 调用 execSql进行数据处理,并加入判断触发断点,通过返回值r判断是否读取到对应数据
- 为防止多次获取同类数据,加入判断,若 datas 不为空,将 datas 内容清楚
if (!datas.empty())
datas.clear();
- 定义智能指针addr,调用_GetLifetimeValue将addr中的内容加到datas中;并判断返回值
- _GetLifetimeValue函数实现如下
void _GetLifetimeValue(const SqliteResult& result, size_t index, shared_ptr<LifetimeAddr> addr)
{
addr->id = result.m_vecValues.at(index).at(0); //添加ID内容到数组容器,位置信息取0
addr->nameId = result.m_vecValues.at(index).at(1);
addr->usedMeter = result.m_vecValues.at(index).at(2);
addr->warnMeter = result.m_vecValues.at(index).at(3);
addr->stopMeter = result.m_vecValues.at(index).at(4);
addr->timeReplace = result.m_vecValues.at(index).at(8);
addr->permission = result.m_vecValues.at(index).at(9);
_GetResultValue(result, index, addr->usedAddr, 5, false, false, false, true);
_GetResultValue(result, index, addr->warnAddr, 6, false, false, false, true);
_GetResultValue(result, index, addr->stopAddr, 7, false, false, false, true);
}
标题- 至此,完成数据的内容已到达 GetLifetime()函数中;将所需数据转化为需要的格式
- 为数据定义数据格式
struct LifetimeAddr
{
LifetimeAddr() :
//构造函数初始化
usedAddr(make_shared<BasePlcAddr>()),
warnAddr(make_shared<BasePlcAddr>()),
stopAddr(make_shared<BasePlcAddr>())
{
}
string id;
string nameId;
string usedMeter;
string warnMeter;
string stopMeter;
string timeReplace;
string permission;
shared_ptr<BasePlcAddr> usedAddr;
shared_ptr<BasePlcAddr> warnAddr;
shared_ptr<BasePlcAddr> stopAddr;
};
- 完成目标数据格式josn格式的转变
string DataMain::Lifetime2Json(const vector<shared_ptr<LifetimeAddr>>& v1)
{
Json::Value root;
_Lifetime2JsonValue(v1, root);
string r = root.toStyledString();
return r;
}
string DataMain::Lifetime2Json()
{
string result= Lifetime2Json(m_vecLifetime);
return result;
return "";
}
_Lifetime2JsonValue ()函数完成Json数据格式转换,内部处理方便给界面层使用(此处写的不是很好,调用了两次,容易混乱,其实目的就是把从数据库读取出的数据,转变为对应格式,方便调用
void DataMain::_Lifetime2JsonValue(const vector<shared_ptr<LifetimeAddr>>& v, Json::Value& root)
{
Json::Value arr;
for (auto i : v)
{
Json::Value tmp;
tmp["id"] = i->id;
tmp["name_id"] = i->nameId;
tmp["usedMeter"] = i->usedMeter;
tmp["warnMeter"] = i->warnMeter;
tmp["stopMeter"] = i->stopMeter;
tmp["usedAddr"] = i->usedAddr->address;
tmp["warnAddr"] = i->warnAddr->address;
tmp["stopAddr"] = i->stopAddr->address;
tmp["permission"] = i->permission;
tmp["timeReplace"] = i->timeReplace;
arr.append(tmp);
}
root["lifetime"] = arr;
}
至此,数据以及可以通过接口GetLifetime()传递出去,接下来要解决接口返回数据写入数据库的问题
- 定义一个返回写入接口
DLL_EXPORT bool CALL_CONV SetWarnAndStopLifeTime(const char* id, const char* warnNull, const char* stopNull, const char* time);
- List item DLL_EXPORT 为宏定义,本质上是_declspec(dllexport)声明,目的为了生成动态库;
- CALL_CONV为宏定义,本质上是_stdcall,目的是约定调用
- 函数实现
DLL_EXPORT bool CALL_CONV SetWarnAndStopLifeTime(const char* id, const char* warnNull,const char* stopNull,const char* time)
{
int r = hmx::sqlite::updates("t_ui_lifetime", "warn", vector<string>{warnNull}, "id", vector<string>{id});
if (r != 0)return false;
r = hmx::sqlite::updates("t_ui_lifetime", "stop", vector<string>{stopNull}, "id", vector<string>{id});
if (r != 0)return false;
r = hmx::sqlite::updates("t_ui_lifetime", "timeReplace", vector<string>{time}, "id", vector<string>{id});
if (r != 0)return false;
r = hmx::sqlite::GetLifetime(g_dataMain->m_vecLifetime);//重新加载数据库数据
if (r != 0)return false;
return true;
- 共需要些入数据库四个参数,依次分别是 id,warn,stop和time,定义函数四个参数(id作为key值,不需要处理)
- 因此调用updates函数对写入数据库,updates函数实现如下
// 更新多条数据的同一个字段的值
int updates(const string& tableName, const string& opKey, const vector<string>& opValues,
const string& conditionKey, const vector<string> conditionValues)
{
SqliteOperate* op = new SqliteOperate(g_currentExePath + "/" + g_sqlitePath, "updateConnect");
if (!op || !op->CheckValid())
return ErrorCode::CONNECT_INVALID;
bool isTranslation = true;
if (isTranslation)
op->Translation();
int r = _updates(tableName, opKey, opValues, conditionKey, conditionValues, op, isTranslation);
if (!r && isTranslation)
op->Commit();
delete op;
return r;
}
- 其中,保证容器性能,采取初始化列表方式使用vector,例vector{warnNull};