成长记录——数据库获取数据转换格式并暴露接口

需求:新功能增加,完成软件新界面增加(包含逻辑与数据)

实现:

  • 获取数据库内容
    • 为接口定义对应的数据格式
    • 完成数据结构组成
    • 数据获取接口实现
    • 数据更改后写入数据库接口实现

获取数据库内容;

  • 首先,已经默认拥有了数据库,并内部已有数据;
  • 定义数据接口
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};

至此,完成修改数据库接口,上层界面可以调用GetLifetime()及SetWarnAndStopLifeTime用于读取数据库及写入数据库操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值