服务端分页处理实现

来源:互联网 发布:李炎恢javascript素材 编辑:程序博客网 时间:2024/06/05 22:42

本文描述如何实现支持分页的应用协议.

1.实现步骤


(1)定义分页条件类
不同应用协议查询条件项可能不同,定义对应的查询条件类,该类从CPageCond派生.
CPageCond是分页条件类.

如:
class CStoreGoodsSaleQueryCond : public CPageCond {public:    string store_id_;    ///< 门店ID    string last_date_;///< 上日日期    unsigned int cmonth_; ///< 当前月份    double total_num_; ///< 合计总金额(符合条件记录的汇总金额)public:    CStoreGoodsSaleQueryCond():cmonth_(0),total_num_(0) {    }};

(2)按以下示例格式编写协议处理函数
本示例中的:
report_->query_goods_sale
执行具体的查询逻辑,对于简单的协议可直接在协议处理函数内完成.

CPagizeHelper为分页处理辅助类.

示例代码如下:
int CMPPlugin::OnQueryStoreGoodsSale((CWrappedMsg<> *in,vector<CWrappedMsg<> *> &out,DISPATCH_RESULT &or) {    CMsg *msg = in->msg;    CPagizeHelper ph;    ph.dbc_name_ = this->local_dbc_.c_str();    CStoreGoodsSaleQueryCond cond;    ///< 从消息中获取分页信息(CPageCond部分)    ph.GetPageCond(msg,&cond);    ///< 从消息中获取CStoreGoodsSaleQueryCond的其它条件项    ...    ///< 执行查询,返回结果保存在vData中    CAutoVector<CGoodsSale*> vData;    int result = report_->query_goods_sale(orgid,userno,&cond,vData);    CMsg *ans = new CMsg;    ///< 把查询结果写入消息包    ...       ///< 写入分页结果信息    ph.PutPageResult(ans,&cond);    DO_RESP(ans,out);     return 0;}

查询逻辑的示例代码如下:
int CReport::query_goods_sale(CQQ_ORGID orgid,CQQ_USERNO userserial,CStoreGoodsSaleQueryCond *cond,vector<CGoodsSale*> &v) {  ...  ///< 处理查询条件    if (!cond->store_id_.empty()) {        where_expr += LogMsg(" and store_id='%s'",cond->store_id_.c_str());    }    CPagizeHelper ph;    ph.dbc_name_ = ; ///< 设置数据库连接       ///< 确定总记录数    if (cond->count_flag_) {        string sql = LogMsg("select count(*) from (select count(*) as cnt_num from %s where %s group by %s having sum(%s)<>0 ) a",tbl_name.c_str(),where_expr.c_str(),group_expr.c_str(),sum_fld.c_str());        int ret = ph.GetCount(sql.c_str(),cond);        if (ret!=1)///< 检查是否有数据            return ret==1 ? -1 : 0;    }    string csql = LogMsg("select a.barcode from %s where %s group by %s having sum(%s)<>0",tbl_name.c_str(),where_expr.c_str(),group_expr.c_str(),sum_fld.c_str());    string tsql = LogMsg("select %s from %s,(%s) c where a.barcode=c.barcode and %s group by %s order by %s desc,a.barcode desc",fld_list.c_str(),tbl_name.c_str(),csql.c_str(),where_expr.c_str(),group_expr.c_str(),order_fld.c_str());    ///< 生成分页查询SQL语句    string sql =  pdbor->GetDBExt()->PageQuery(tsql,cond->begin_pos_,cond->page_size_);    AUTO_QUERY_RECORDSET(CRecordset,prs,pdbor);    ///< 执行查询    prs = pdbor->Query(adCmdText,sql.c_str());    ///< 查询结果输出到对象    CRecordsetBindObject<CGoodsSale> binder;    binder.BindRecordset(prs);    binder.BindField(NEW_FIELD_BIND(CGoodsSale,ORM_FIELD_TYPE_STRING,0,barcode_,0));    binder.BindField(NEW_FIELD_BIND(CGoodsSale,ORM_FIELD_TYPE_STRING,0,goods_name_,1));    while(!prs->IsEof()) {        CGoodsSale *item = binder.ToObject();        v.push_back(item);        prs->Move();    }    return 0;}



2.资源

  • CPageCond在common\base_type2.h文件中定义
  • CPagizeHelper对应的定义文件和实现文件为common目录下的PagizeHelper.h/PagizeHelper.cpp.

3.定义


  • 协议参数
UMX协议中分页参数的定义
///< 请求消息参数名#define PAGIZE_FLAG  "#PAGIZE.FLAG"  ///< 是否需要分页#define PAGIZE_PAGE_NO "#PAGIZE.PAGE_NO" ///< 页号(从1开始)#define PAGIZE_PAGE_SIZE "#PAGIZE.PAGE_SIZE" ///< 页大小#define PAGIZE_COUNT_FLAG "#PAGIZE.COUNT_FLAG" ///< 是否返回总记录数,默认第1页自动返回记录总数#define PAGIZE_PAGE_NO_DUP "#PAGIZE.PAGE_NO_DUP" ///< 是否在返回消息中包含页号///< 返回消息参数名#define PAGIZE_TOTAL "#PAGIZE.TOTAL"  ///< 总记录数

这些参数的访问只通过CPagizeHelper进行。

  • CPageCond
///< 分页条件类class CPageCond {public:    bool page_flag_; ///< 是否分页    ///< 分页查询条件项    unsigned long begin_pos_; ///< 起始位置    unsigned int page_size_; ///< 每页记录数,默认20条    unsigned int page_no_; ///< 页号(从1开始)    bool count_flag_; ///< 是否返回总记录数,默认:false    bool page_no_dup_; ///< 是否在返回消息中记录当前页号    unsigned long total_rec_num_; ///< 总记录数    CPageCond():page_flag_(true),begin_pos_(0),page_size_(20),count_flag_(false),total_rec_num_(0),page_no_(1),page_no_dup_(false) {    }};



  • CPagizeHelper
///< 分页处理帮助类class CPagizeHelper {public:    string dbc_name_; ///< 操作的数据库连接名public:       ///< 从请求中获取分页条件信息    static void GetPageCond(CMsg *req,CPageCond *cond);    ///< 把分页条件置入请求消息    static void PutPageCond(CMsg *req,CPageCond *cond);    ///< 设置返回消息的分页结果信息(统计类)    static void PutPageResult(CMsg  *out,CPageCond *cond);    static void GetPageResult(CMsg  *out,CPageCond *cond);    ///< 获取分页查询记录总数()    ///< @param sql: 查询总数的SQL语句    ///< @return  0:没有数据 1:有数据 -1:错误    int GetCount(const char *sql,CPageCond *cond);       ///< 执行一个只返回一条记录的查询,把列值放入_variant_t数组    ///< @return 0:成功 -1:失败    int QueryRecord(const char *sql,vector<_variant_t> &v);};



4.说明

  • 数据库扩展IDBExt接口中支持分页的方法有三种:PageResult,PageResult2,PageQuery.
其中,PageQuery是最通用和简明的,但效率可能不是最好的.
PageQuery分页处理要求必须提供一个排序字段.
  • 客户端使用CPagizeHelper:
    客户端文件仅需保留以下2个方法的定义和实现:
    static void PutPageCond(CMsg *req,CPageCond *cond); ///< 设置分页查询条件后,写入请求消息包
    static void GetPageResult(CMsg  *out,CPageCond *cond);
   
    .请求时:
    CMsg *req = new CMsg;       ///< 设置消息内容    ...       CPageCond cond;    cond.page_size_ = 50; ///< 每页50条记录    cond.page_no_ = 1;///< 查询第1页       PutPageCond(req,&cond);    Send(req);
    .得到响应时,
    CMsg *ans; ///< 返回的消息包       CPageCond cond;       GetPageResult(ans,&cond);       cond.total_rec_num_;///< 得到总记录数

原创粉丝点击