服务端分页处理实现


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

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_;///< 得到总记录数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值