插件开发技术说明(12)---面向业务对象编程:2种风格的对比
2015-06-26 19:13
661 查看
实现业务功能时要求面向业务对象编程,并且是完全对象化处理。
协议处理不要直接操作数据库,而是通过业务对象的封装完成。
以下是7125协议的2种实现。
这种方式的实现的问题:
。记录未锁定:存在并发问题
。非完全面向对象:业务逻辑和数据结构裸露
相关定义与实现代码
协议处理不要直接操作数据库,而是通过业务对象的封装完成。
以下是7125协议的2种实现。
风格1:
int CSbaService::OnApplyTrial(CWrappedMsg<> *in,vector<CWrappedMsg<> *> &out,DISPATCH_RESULT &or) { or.err_code_ = CE_DATABASE; CMsg* pMsgIN = in->msg; long lEId=0,lUserId=0,lCoEId,lGoodsId=0,lApplyNum=0; if(-1==pMsgIN->GetParam("EId",lEId) || -1==pMsgIN->GetParam("UserId",lUserId) || -1==pMsgIN->GetParam("CoEId",lCoEId) || -1==pMsgIN->GetParam("GoodsID",lGoodsId) || -1==pMsgIN->GetParam("ApplyNum",lApplyNum)) { or.err_code_ = CE_PARAM_ERROR; return -1; } GETDBC(pdbor,local_dbc_.c_str()); FAIL_RETURN(pdbor->BeginTrans(),,-1); CTrialSale* pVenTrialSale = CTrialSale::Get((int)lCoEId,(int)lGoodsId); if( pVenTrialSale->IsOutofdate() || pVenTrialSale->IsOverbalanceTotal((int)lApplyNum) ) ///<过期,申请超量 { or.err_code_ = CE_DATA_ERROR; return -1; } if(pVenTrialSale->GetLimitBQty() - pVenTrialSale->GetApplyQty()<lApplyNum) ///< 判断是否超出总量 { return -1; } ///< 查询门店已申请数量 string strSql = LogMsg("select sum(applyqty) from t_ven_applytrial where refobjectid=%d and eid=%d", pVenTrialSale->GetObjectId(), lEId); unsigned long ulSumNum = 0; int nRes = CQueryFunc::Query(pdbor, strSql, ulSumNum); if(-1==nRes || 0==nRes) { return -1; } if(pVenTrialSale->IsOverbalanceSingle(ulSumNum + lApplyNum)) ///< 判断是否超出每个门店可以申请的数量 { or.err_code_ = CE_DATA_ERROR; return -1; } strSql = LogMsg("insert into t_ven_applytrial(refobjectid,eid,applyqty,applytime,proposer) values(%d,%d,%d,GetDate(),%d)", pVenTrialSale->GetObjectId(),lEId,lApplyNum,lUserId); string sql = LogMsg("update t_Ven_TrialSale set ApplyQty=ApplyQty+%d where eid=%d and goodsid=%d",lApplyNum,lCoEId,lGoodsId); if (!pdbor->Execute(strSql.c_str())) { return -1; } if (!pdbor->Execute(sql.c_str()) ) { return -1; } FAIL_RETURN(pdbor->CommitTrans(),,-1); return 0; }
这种方式的实现的问题:
。记录未锁定:存在并发问题
。非完全面向对象:业务逻辑和数据结构裸露
风格2:
todo: 增加业务错误码int CSbaService::OnApplyTrial(CWrappedMsg<> *in,vector<CWrappedMsg<> *> &out,DISPATCH_RESULT &or) { or.err_code_ = CE_DATABASE; CMsg* pMsgIN = in->msg; long lEId=0,lUserId=0,lCoEId,lGoodsId=0,lApplyNum=0; CHECK_MSG_PARAMETER2(pMsgIN,"EId",lEId,-1); CHECK_MSG_PARAMETER2(pMsgIN,"UserId",lUserId,-1); CHECK_MSG_PARAMETER2(pMsgIN,"CoEId",lCoEId,-1); CHECK_MSG_PARAMETER2(pMsgIN,"GoodsID",lGoodsId,-1); CHECK_MSG_PARAMETER2(pMsgIN,"ApplyNum",lApplyNum,-1); GETDBC(pdbor,local_dbc_.c_str()); FAIL_RETURN(pdbor->BeginTrans(),,-1); ///< 读指定供应商指定商品的试销信息(在有效期内只能由一条有效记录) ///< 只取有效试销信息,需要锁定读取的记录以便后续修改已申请数 CTrialSale* trial_sale = CTrialSale::Get((int)lCoEId,(int)lGoodsId,true,true); ///< 检查总量限量是否已到 if (!trial_sale->CheckTotalQty()) { return -1; ///< 总量已申请完 } CTrialApply trial_apply; ///< 试销申请对象 ///< 为试销申请成员赋值 trial_apply.trial_sale_ = trial_sale; ///< 试销申请关联的试销商品信息对象 trial_apply.eid_ = lEId; trial_apply.creator_ = lUserId; trial_apply.co_eid_ = lCoEId; trial_apply.apply_qty_ = lApplyNum; ///< 本次申请数量 int ret = trial_apply.CanApply(); ///< 检查是否可申请 if (ret==-1) ///< 错误产生 return -1; if (ret==0) { ///< 申请超量 or.err_code_ = CE_DATA_ERROR; return -1; } ///< 生成单据编号 if (trial_apply.ApplyID()) return -1; CDateTime::GetDateTime(trial_apply.create_time_); ///< 写入数据库 if (trial_apply.Insert()) { return -1; } ///< 增加已申请数量 trial_sale->m_nApplyQty += lApplyNum; ///< 更新试销商品信息 if (trial_sale->Update()) return -1; FAIL_RETURN(pdbor->CommitTrans(),,-1); return 0; }
相关定义与实现代码
class CTrialApply : public CSheet { public: SLIC_OBJECTID ref_object_id_; ///< 关联试销商品记录编号 float apply_qty_; ///< 申请数量 float accept_qty_; ///< 确认数量 CTrialSale *trial_sale_; ///< 试销商品对象 public: CTrialApply():CSheet(),ref_object_id_(0),apply_qty_(0),accept_qty_(0),trial_sale_(0) { sheet_type_ = 1060; } int Insert(); int CanApply(); ///< 是否能申请 }; ////////////////////////////////////////////////////////////////////////// int CTrialSale::Update() { USEDBC(pdbor,CDataEnv::env_->dbc_name_.c_str()); ITableHandler *th = CDataEnv::env_->db_helper_->NewTableHandler(pdbor,"t_Ven_TrialSale"); AUTO_POINTER_NODECLARE(ITableHandler,th); th->BindField("ObjectId",(char**)&this->m_nObjectId,sizeof(this->m_nObjectId)); th->BindField("ApplyQty",(char**)&this->m_nApplyQty,sizeof(this->m_nApplyQty)); th->SetKeyField("ObjectId",0); if (th->Insert()) return -1; return 0; } ////////////////////////////////////////////////////////////////////////// int CTrialApply::CanApply() { int applied_qty = trial_sale_->QueryAppliedQty(this->eid_); if (applied_qty==-1) return -1; return (applied_qty+this->accept_qty_)<trial_sale_->m_nLimitBQty ? 1:0; } ////////////////////////////////////////////////////////////////////////// int CTrialApply::Insert() { USEDBC(pdbor,CDataEnv::env_->dbc_name_.c_str()); ITableHandler *th = CDataEnv::env_->db_helper_->NewTableHandler(pdbor,"t_ven_applytrial"); AUTO_POINTER_NODECLARE(ITableHandler,th); th->BindField("RefObjectId",(char**)&this->ref_object_id_,sizeof(this->ref_object_id_)); th->BindField("EId",(char**)&this->eid_,sizeof(this->eid_)); th->BindField("ApplyQty",(char**)&this->apply_qty_,sizeof(this->apply_qty_)); th->BindField("Proposer",(char**)&this->creator_,sizeof(this->creator_)); th->BindField("ApplyTime",this->create_time_); if (th->Insert(false)) return -1; return 0; } ////////////////////////////////////////////////////////////////////////// CTrialSale* CTrialSale::Get(int nEId,int nGoodsId,bool active,bool lock) { string expr; if (active) { string today = CDateTime::Now().GetDateTime(); expr = LogMsg(" and (DataType=0 or (cast('%s' as datetime)>=bdate and cast('%s' as datetime)<=edate))",today.c_str(),today.c_str()); } USEDBC(pdbor,CDataEnv::env_->dbc_name_.c_str()); string strSql = LogMsg("select ObjectId,EId,GoodsID,LimitBQty,LimitQty,ApplyQty,SaleQty,DateType,BDate,EDate,CreateTime " " from t_Ven_TrialSale %s where eid=%d and goodsid=%d %s %s", lock ? pdbor->GetDBExt()->WithLock().c_str() : "",nEId,nGoodsId,active ? expr.c_str() : "",lock ? pdbor->GetDBExt()->ForUpdate().c_str():""); AUTO_QUERY_RECORDSET(CRecordset,prs,pdbor); prs = pdbor->Query(adCmdText,strSql.c_str()); if (prs==0 || prs->IsEof()) { return NULL; } CRecordsetBindObject<CTrialSale> binder; binder.BindRecordset(prs); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nObjectId,"ObjectId")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nEId,"EId")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nGoodsId,"GoodsID")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nLimitBQty,"LimitBQty")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nLimitQty,"LimitQty")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nApplyQty,"ApplyQty")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_INT,0,m_nSaleQty,"SaleQty")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_UINT,0,m_unDateType,"DateType")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_STRING,0,m_strBDate,"BDate")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_STRING,0,m_strEDate,"EDate")); binder.BindField(NEW_FIELD_BIND(CTrialSale,ORM_FIELD_TYPE_STRING,0,m_strCreateTime,"CreateTime")); return binder.ToObject(); }
相关文章推荐
- python之列表常见操作
- fatal error C1083: Cannot open include file: 'qttreepropertybrowser.moc': No such file or directory
- Java中ArrayList类的用法(转)
- Java 持有对象
- python之环境搭建windows版
- java获取当前系统信息
- asp.net Js里面用padLeft ()方法
- VBA遍历文件夹的三种方法(转载)
- Python学习笔记_Python基础
- MATLAB 随机生成互不重叠的多个矩形
- 如果Python中有很多换行,可以选择使用"""..."""表示多行内容
- Java主线程等待所有子线程执行完毕再执行解决办法
- python中转义用法 r''
- 深入探究JVM(1) - Java的内存区域解析
- PHP基础温习之echo print printf sprintf print_r var_dump的用法与区别
- Django折腾记之启动定时任务
- 如何理解和编程实现证据理论的Dempster组合规则?
- ICTCLAS2015 Java版本的使用方法
- lua string.dump
- C语言概述