新查询模板技术红皮书NC-UAP5.5用友NC-UAP目录前言........................................................................................................................................3第一章设计介绍.....................................................................................................................61.1模型介绍....................................................................................................................61.2默认编辑器及扩展机制.............................................................................................71.3查询模板与数据权限.................................................................................................91.4查询树的查询优化...................................................................................................11第二章开发说明...................................................................................................................132.1调用方式..................................................................................................................132.1.1自己实现过查询对话框的情况............................................................................132.1.2无自己写查询模板的单据....................................................................................132.1.3常用条件Panel的使用.........................................................................................142.1.4数据权限控制........................................................................................................142.1.5事件监听...............................................................................................................152.2FAQ...........................................................................................................................17附录......................................................................................................................................20附一查询条件表中个字段含义....................................................................................20附二系统函数列表........................................................................................................22专题一:定制自定义SQL....................................................................................................23专题二:查询模板事件响应.................................................................................................29前言查询模板的功能比较单纯,用一句话概况就是,接受用户的输入,构造SQL语句的Where条件。另外还可以通过设置固定条件和启用数据权限实现对用户的所能查询的数据做一定的限制。V55对查询模板重新做了设计(以下称新查询模板)准备逐步替换原来的查询模板(以下称老查询模板)。老查询模板主要存在问题是:操作不方便,不够直观,尤其是在定义复杂条件时。无法支持对括号的嵌套,无法支持一些复杂条件,比如Aand(Bor(CandD))图1老查询模板新版查询模板较之旧查询模板明显优点:新查询模板设计了“常规”和“高级”两个视图,分别针对简单条件和复杂条件的编辑。常规视图采用Form形式,使简单条件(查询条件都是And联接)的录入更方便。高级视图采用了类似ClearQuest的树形查询编辑器的形式,避免了括号的输入,使得复杂条件的设置比老查询模板要简单和直观。增加了Between操作符,可以替换各产品组定制的常用条件的“从…到…”类条件。增强了等于操作符,使其能支持多选(相当把原来的等于和in操作符合成一个了,单独的in操作符仍然支持),这样可以消除实际操作时对“或者(or)”操作符的需要,加强了常规视图的实用性。增加了排序页签,可以在页面上添加排序字段,然后得到排序的sql语句,调用者将排序语句拼接到sql语句中完成查询的排序功能。图2新查询模板常规视图图3新查询模板高级视图图4新查询模板排序页签第一章设计介绍1.1模型介绍查询模板最终形成的Where条件总是由若干个相对独立的小条件通过and和or操作符组合合成的。比如:部门=’生产部’and(人员编码=’P0001’or人员编码=’P0003’)。在新查询模板中,这样每个独立的小条件由一个IFilter接口来描述。IFilter又分成三个组成部分,元信息(IFilterMeta),操作符(IOperator),和字段取值(IFieldValue)。图2.1Filter类结构图FilterMeta(IFilterMeta的在查询模板中的默认实现)描述了条件字段的元信息,相当于老查询模板的QueryConditionVO。FilterMeta目前实际就是通过把QueryConditionVO进行转换操作后生成的,或从单据元数据生成。IOperator接口是对操作符的抽象。IFileldValue接口是对字段取值的抽象,它实际只有一个方法,即返回一个IFieldValueElement的集合。IFieldValueElement是对一个“原子”值的抽象,实际可能是描述了一个整数,或者是一个枚举值,或者是参照返回值。整个的Where条件就可以看成由and,or操作符以及IFilter形成的一棵树,在新查询模板中以QueryTree来描述。前面举的例子,表示成树的形式就如下图所示。图2.2查询条件树And部门=’生产部’Or人员编码=’P0001’人员编码=’P0002’不论是高级视图还是常规视图,其内部都是用QueryTree来组织单个的IFilter的。QueryTree及相关类结构图如下图所示:图2.3QueryTree相关类结构图1.2默认编辑器及扩展机制基于前面的模型,查询模板从功能上就可以理解为一个是能对QueryTree和IFilter进行编辑的编辑器。对QueryTree的编辑实际就是把IFilter看成最小的单元,提供一定的方法,让用户修改IFilter之间的与或关系。对于常规视图来说,用户不用关心,实际也不能修改,IFilter之间的与或关系。常规视图上的IFitler都是“与(AND)”的关系,用户不能修改,只能增加或删除IFilter。对于高级视图,用户可以则可以任意调整IFilter之间的与或关系,从而构造出复杂的查询条件。新查询模板对QueryTree的编辑没有设计扩展机制,因为对与或关系的编辑没有太多的特殊性需求,常规视图和高级视图已经能完全满足简单条件和复杂的条件的编辑了。但是对于IFilter的编辑,往往是和具体的业务相关的,默认的编辑方式不一定能满足业务的要求。因此新查询模板针对这个问题重点做了设计,支持在不同层次上对IFilter编辑进行扩展。对IFilter进行编辑的编辑器被抽象为接口IFilterEditor,当查询模板需要一个IFilter的编辑器,即一个IFilterEditor实例时,会调用FilterEditorManager创建出一个。默认的情况下查询模板创建出来的是DefaultFilterEditor,如图2.4所示。如果DefaultFilterEditor不能满足业务的需要,则可以按需定制符合要求的编辑器,并注册到FilterEditorManager中,即可实现对DefaultFilterEditor的替换。图2.5展示了一个定制的FilterEditor,对于“经济类型”这样的枚举型字段,采用图示的编辑器可能更方便。2.4默认编辑器2.5自定义编辑器图2.4中被红色线框框住的部分即是DefaultFilterEditor,它由三部分组成:左边是显示FilterMeta的Label控件,中间是供选择操作符的下拉框控件,右边被绿色线框框住的部分是对IFieldValue进行编辑的编辑器,抽象为IFieldValueEditor,默认情况下创建出来的是DefaultFieldValueEditor,同DefaultFilterEditor一样,通过FieldValueEditorManager注册定制的编辑器,DefaultFieldValueEditor也是可以被替换的。如前文所述,IFieldValue是对IFieldValueElement包装,而DefaultFieldValueEditor实际上是对IFieldValueElementEditor的包装。DefaultFieldValueEditor包含了两个IFieldValueElementEditor的实例,根据用户所选择的操作符的不同会有不同的界面展现。图2.4中选择的是“介于”操作符,它是一个接受2个参数的操作符,因此DefaultFieldValueEditor把两个IFieldValueElementEditor都显示出来了。如果是其他情况,即操作符是接受0个,1个,任意多个参数时,DefaultFieldValueEditor总是显示一个IFieldValueElementEditor,但会根据操作符接受参数的个数,设置IFieldValueElementEditor是否允许多选。上面所描述的DefaultFieldValueEditor的行为如果符合业务的需要,那么你可以坦然接受它,反之则是定制你自己的IFieldValueEditor的时候了。在没替换DefaultFieldValueEditor的情况下,用户在为某个查询条件选定一个部门,或者一个公司,或者输入一个订单货品的数量,实际都是通过IFieldValueElementEditor进行的,而后者是通过IFieldValueElementEditorManager创建出来的,默认的情况下它又把这个任务委托给了DefaultFieldValueElementEditorFactory这个工厂类。这个工厂类根据注册在pub_query_condition的信息,主要是字段的数据类型等信息,生产出合适的IFieldValueElementEditor实例。同样地,这个过程也是可以根据需要扩展的,支持注册定制的IFieldValueElementEditor。综上所述,新查询模板对IFilter的编辑,分别在IFilterEditor,IFieldValueEditor,IFieldValueElementEditor三个层次上提供了扩展机制,在实际使用时可以根据情况具体选择扩展方式。图2.6是相关的类图,从中可以看到,这三个层次的扩展机制是完全相同的。都是由一个IXXEditor接口来表示编辑器,然后有一个IXXEditorFactory的工厂来负责创建编辑器,一个XXEditorManager来管理工厂。注册一个定制的编辑器,概况来讲可以分成三个步骤,1.提供一个实现了IXXEditor接口的自定义编辑器2.提供一个相应的工厂类,负责生产该自定义编辑器3.把该工厂类注册到XXEditorManager中。关于如何注册,请参看开发说明有关章节。图2.6IFilter编辑器相关类图1.3查询模板与数据权限NC中需要控制数据权限的业务节点,对于查询操作的控制,即限制用户仅能查询到其有权限的数据,一般是通过查询模板来实现的。其原理是由查询模板在用户设置的查询条件后面自动附件数据权限相关的条件。举例来说,订单上有经销商(custom),存货(inv)等字段。现在需要限制某个用户仅能查询特定的经销商和特定的存货订单。用户A,其有权限的经销商为C1,C2,C3,其有权限的存货为I1,I2,I3。那么当用户A对订单执行查询操作时,不论其设置的条件是什么查询模板都必须附加如下的SQL语句。(customisnullorcustomin('C1','C2','C3'))and(invisnullorcustomin('I1','I2','I3))当然对于订单来说,其经销商和存货字段一般都是不可为空的,上面的"customisnull"这样的条件有些多余,但如果对于其他可以为空的字段则必须加上这样的条件,否则查询出来的结果可能是不完全的。业务组对于某些为空字段设置为特定字符串来提高效率,对于这种情况,需要在调用模板时在模板信息中添加欲替换的字符串信息。另外实际查询模板拼接出来的sql不会象上面一样是用('C1','C2','C3')这样的形式枚举其有权限的数据而是一个有权限服务提供一个子查询sql语句。实际的sql是以下的形式bd_cubasdoc.pk_areaclisnullorbd_cubasdoc.pk_areaclin(selectdistinctpower.resource_data_idfromsm_power_areaclasspower,sm_useru,sm_user_roleurolewhereu.cuserid='0001SD100000000000UP'andu.cuserid=urole.cuseridandurole.pk_corp='1001'andurole.pk_role=power.pk_roleandpower.orgtypecode=1and(power.pk_org='1001'oriscommon_powerin('y','Y'))NC的权限不但和角色相关,和角色所属的组织也相关,即权限实际上描述了,角色,组织和资源之间的关系。在上面的例子里,忽略了多个组织的情况。因为一般情况下对一个单据的查询实际上有个隐含的限制条件,即查询当前角色所登录的组织(公司或者主体账簿)的单据。当要需要对多个组织的数据进行查询时,则数据权限的附件条件要比上面复杂许多。还是上面的例子,现在需要指出订单上还有一个字公司(pk_corp)字段,即表示订单是按照公司的组织维度来区分的。现在用户A有权限查询的公司为(O1,O2),并且对于公司o1,其有权限的经销商为(C1,C2),有权限的存货为(I1,I2);对于公司o2,其有权限的经销商为(C2,C3),有权限的存货为(I2,I3)。那么用户A对公司o1和o2的数据进行查询时,需要附加的数据权限相关条件如下:((pk_corp='o1'and(customisnullorcustomin('C1','C2'))and(invisnullorinvin('I1','I2')))or(pk_corp='o2'and(customisnullorcustomin('C2','C3'))and(invisnullorinvin('I2','I3'))))同样上面的语句只是示意,实际的过程是对于每个公司都需要向权限服务获取字段custom和inv对应的数据权限子查询,然后组合成最终的条件。关于数据权限具体,参见开发说明之多公司的数据权限控制。1.4查询树的查询优化如果查询模板涉及到主子表关系,内推条件查询等情况,需要查询树进行查询优化。优化具有两个前提条件:1、查询条件是可以合并的;2、可合并的查询条件要在同一个逻辑操作符下。下面以几个例子来描述优化过程。如下面这个查询树如果不经过优化,那么它生成的查询条件是:(o.c.code=’001’oro.c.name=‘tiger’oro.no=‘55001’)ando.p=’superman’如果我们认为订单.客商.编码和订单.客商.名称是可以合并(下一章介绍如何判断可合并)的则合并后的查询树变为生成的语句是:(o.c.(code=’001’orname=’tiger’)oro.no=‘55001’)ando.p=’superman’查询树优化过程实际就是可合并的查询条件合并的过程,该过程会有两种不同处理方式,第一种方式,就是如上面两幅图所示,在同一操作符下,除了能合并的条件外还有不能合并的条件,即合并后该逻辑操作符下还有两个以上的查询条件,那么只需将合并后的查询条件替换原来未合并的查询条件即可。第二种方式如下图所示:即,如果一个逻辑操作符下所有的查询条件都合并了,那么删掉该逻辑操作符,合并后的节点挂到上级节点上。优化是从下级节点到上级节点递归的过程。第二章开发说明2.1调用方式2.1.1自己实现过查询对话框的情况新老查询模板的调用方式如下表所示:旧的方式新的方式查询对话框nc.ui.pub.query.QueryConditionClient(含引用和继承)nc.ui.querytemplate.QueryConditionDLG得到常用条件panelgetUIPanelNormal()getNormalPanel()获取查询语句getWhereSQL()getWhereSQL()可见NormalPanelsetNormalShow;hideNormal()setVisibleNormalPanel(boolean)可见用户自定义PanelsetShowDefine;hideDefinesetVisibleUserDefPanel(boolean)获取排序语句无getOrderSql()获取查询描述getSqlDscrpt()获取无数据权限查询条件无getWhereSqlWithoutPower()查询模板数据setTemplateID(..)如果需要指定的templateid,只需要在传入的参数templateinfo中设置其templateid即可;如果确实外面想在show之前自己加载数据,可以调用方法initUIData代码样例:继承查询对话框样例代码可参见:nc.ui.trade.query.HYQueryConditionDLG该类只适用于UI工厂,产品组请勿继承和调用之,且参照之即可。否则以后代码更改概不负责。直接调用样例代码示例:TemplateInfotempinfo=newTemplateInfo();tempinfo.setPk_Org(ClientEnvironment.getInstance().getCorporation().getPrimaryKey());tempinfo.setCurrentCorpPk(ClientEnvironment.getInstance().getCorporation().getPrimaryKey());tempinfo.setFunNode(getModuleCode());tempinfo.setUserid(ClientEnvironment.getInstance().getUser().getPrimaryKey());queryDlg=newQueryConditionDLG(this,null,tempinfo);queryDlg.showModal();2.1.2无自己写查询模板的单据采用与UI工厂原先类似的方法。只是把nc.ui.trade.query.HYQueryDLG替换为nc.ui.trade.query.HYQueryConditionDLG。一般用UI工厂做的查询模板不需要考虑这个。2.1.3常用条件Panel的使用在新的查询模板中,常用条件会加载到自定义条件上方,使用带有INormalQueryPanel参数的nc.ui.querytemplate.QueryConditionDLG构造子创建查询对话框,将自己定义的常用条件传入即可,自己定义的常用条件必须要实现INormalQueryPanel接口。如果要把对应的常用条件保存到我的收藏夹(即查询模板的个人历史保存),则需持久化常用条件,那么必须实现接口中setNormalQueryObject和getNormalQueryObject方法,且序列化的对象和字段不能为transient。常用条件示例代码如下,该段代码效果如前言图2,图3分割线以上所示:privateclassTestNormalPanelextendsUIPanelimplementsINormalQueryPanel{privateUILabellabel=newUILabel("Fillthetxt:");privateUITextFieldtxtField=newUITextField(30);publicTestNormalPanel(){super();add(label);add(txtField);}publicJComponentgetComponent(){returnthis;}publicObjectgetNormalQueryObject(){returntxtField.getText();}publicvoidsetNormalQueryObject(ObjectqryObject){txtField.setText(qryObject==null?"":String.valueOf(qryObject));}publicvoidclearData(){txtField.setText("");}publicvoidreSetData(){}}2.1.4数据权限控制涉及到跨组织的数据权限控制,在查询模板中有两种情况单字段---即所有权限字段依赖于单一的字段(一对多关系)多字段---即不同的权限字段可能依赖于不同的字段(多对多关系)要在初始化查询页面时设置好数据与组织的依赖关系,(即在TemplateInfo中设置之),示例代码如下://step1:设置权限组织字段PowerCorrelationVOpcvo=newPowerCorrelationVO();pcvo.setOrgFieldcode("bd_cubasdoc.pk_corp1");//step2:设置被关联的字段pcvo.addCorrelatedFieldcode("bd_cumandoc.pk_resppsn1");pcvo.addCorrelatedFieldcode("bd_cumandoc.pk_respdept1");templateinfo.addPowerCorrlationVO(pcvo);//<li>多字段PowerCorrelationVOpcvo2=newPowerCorrelationVO();……(同上)templateinfo.addPowerCorrlationVO(pcvo2);//调用查询界面构造子数据权限是否启用有开关控制,其控制开关为TemplateInfo中的如下字段/***是否数据权限控制.(适用于旧版的逻辑,即其启用或者字段启用,则控制权限)*/privatebooleanisDataPowerCtrl=false;/***数据权限强制开关.(5.3后适用,即总开关作用,其优先级最高)*/privatebooleandataPowerForceSwitch=true;同时可以控制每个候选条件是否启用数据权限,可以静态的通过初始化设置条件是否启用数据权限,也可以根据需求动态的来设置该条件是否启用数据权限,实现数据权限判断器IDataPowerEnableJudger并使用registerDataPowerEnableJudger(IDataPowerEnableJudgerjudg)将其注册到查询模板中。2.1.5事件监听如2.2所述,可以根据不同的需要注册编辑器来实现自己的需求,但注册的方式是在加载模板数据的时候做的。如果数据加载以后,需要根据某些操作的结果来决定其他Filter或Fltereditor属性就需要用查询模板的事件监听机制来实现。被监听的事件定义在nc.ui.querytemplate.CriteriaChangedEvent中,包括如下事件:FILTER_CHANGEDFilter改变事件,包括Filter的值改变和操作符改变FILTER_REMOVEDFilter移除事件,从条件编辑器中删除该Filter触发FILTEREDITOR_INITIALIZEDFltereditor初始化事件,添加Filter和在高级视图中修改Filter时触发OPERATOR_CHANGED操作符改变事件,高级视图修改关系操作符(and,or)时触发,目前未使用。要使用查询模板事件监听机制,需要实现ICriteriaChangedListener接口,并将其使用QueryConditionDLG的registerCriteriaEditorListener(ICriteriaChangedListenerlistener)方法注册到查询模板中,以下是示例代码:QueryConditionDLGqcd=newQueryConditionDLG(panel,tnp,tempinfo);qcd.registerCriteriaEditorListener(newICriteriaChangedListener(){publicvoidcriteriaChanged(CriteriaChangedEventevent){if(event.getEventtype()==CriteriaChangedEvent.FILTER_CHANGED){if(event.getFieldCode().equals("unitcode")){List<IFilter>fi=event.getCriteriaEditor().getFiltersByFieldCode("pk_corp");for(inti=0;i<fi.size();i++){//event.getCriteriaEditor().clearData(fi.get(i));//清空if(event.getFilter().getFieldValue().getFieldValues().get(0).getValueObject().equals("1002")){corpcode="1002";event.getCriteriaEditor().setFilterValue(fi.get(0),"1002");}else{corpcode="";event.getCriteriaEditor().setFilterValue(fi.get(0),"1004");}}}}if(event.getEventtype()==CriteriaChangedEvent.FILTEREDITOR_INITIALIZED){if(event.getFieldCode().equals("pk_corp")){DefaultFilterEditordfe=(DefaultFilterEditor)event.getFiltereditor();if(corpcode.equals("1002")){FilterEditorChangedUtil.setRefModel(dfe,"采购组织",null);}else{FilterEditorChangedUtil.setRefModel(dfe,"公司目录","0001");FilterEditorChangedUtil.setRefPk(dfe,"1004");}}}}});*注:FilterEditorChangedUtil是编辑器改变工具类,目前处理对参照编辑器的各种改变,包括取值,设置where条件,设置RefModel等,可根据业务组具体要求扩展。在使用查询模板事件监听机制时需要注意的是普通视图和高级视图是有差别的,那就是普通视图不但存在Filter同时Filter的编辑器也一直存在在视图上,而高级视图上只有Filter,只有在创建新的Filter或修改已有Filter时才会以对话框形式初始化相应的编辑器。详细可以参见专题二。2.2FAQ为了更直观的解决使用查询模板开发过程中遇到的问题,先将常用问题解答列出:Q1:老模板可以拿到ConditionVO,新模板怎么得到呢?答:新版本查询模板将查询模板内部的数据结构封装,不对外提供,有特殊需求的可以提需求,UAP提供service解决。Q2:如何设置参照和下拉的默认值?默认值可以是多选吗?答:如果是参照,在默认值中写参照结果的pk,多选用“,”分离;如果是combobox,要看数据怎样注册的,如果是i,c那么默认值为序号,如果是s那么默认值是显示值,多选用“,”分离。例如:I,aa,bb,cc如果想要默认值为aa,bb则默认值注册为0,1S,aa,bb,cc则为aa,bbQ3:如何在程序中动态的处理查询条件呢?答:在数据库中模板数据基础上过滤,修改(如自定义项的处理),增加查询条件,需要注册一个模板VO处理器。然后具体调用示例代码:qcd.registerQueryTemplateTotalVOProceeor(newIQueryTemplateTotalVOProcessor(){publicvoidprocessQueryTempletTotalVO(QueryTempletTotalVOtotalVO){if(totalVO!=null){QueryConditionVO[]qryconds=totalVO.getConditionVOs();for(QueryConditionVOqcvo:qryconds){if(qcvo.getFieldCode().equals("bd_purorg.mobile")){qcvo.setIfUsed(UFBoolean.FALSE);qcvo.setIsCondition(UFBoolean.FALSE);qcvo.setValue("xxx");}}}}});Q4:如何给特定的查询的参照,设置过滤条件?答:这相当于要对值编辑器做一定的控制,在新模板中通过注册值编辑器工厂来处理,具体代码如下所示:qcd.registerFieldValueEelementEditorFactory(newIFieldValueElementEditorFactory(){publicIFieldValueElementEditorcreateFieldValueElementEditor(FilterMetameta){if("pub_systemplate.operator".equals(meta.getFieldCode())){UIRefPanerefPane=newUIRefpaneCreator(m_queryDlg.getQueryContext()).createUIRefPane(meta);refPane.setWhereString("pk_corp='"+getCurrPK_corp()+"'");returnnewRefElementEditor(refPane,meta.getReturnType());}returnnull;}});另外涉及到编辑器操作的都可以用该方法实现,例如改变参照的Model,创建自己定义的下拉框等。Q5:如何定制某个查询条件返回的sql呢?答:该问题相对复杂,参见专题一。Q6:对于以前注册为字段值列表(pub_dd)的字段,该如何在新的查询模板中应用呢?答:这有两种情况(一)对于原来的取值为pub_dd表中szqz(数值取值),则仍然按照原来的设置即可。(二)而对于有可能的zfqz(字符取值),或xh(序号),旧模板通常需要自己再去获得想要的取值,而新的查询模块,不允许外面调用者自己去拼写SQL。所以,增强注册说明,即扩展consultcode.参见查询条件表中字段说明。Q7:对于那些不是用来拼写SQL的条件如何组织呢?答:可以有两种方式来解决,即逻辑条件和常用条件:常用条件:在前文中已有介绍(参见2.1.3常用条件Panel的使用),调用者自己获取常用条件值写逻辑处理之。逻辑条件:查询条件有属性是否查询条件(isCondition)该属性设为false那么该条件即为逻辑条件,逻辑条件不拼入sql,相当于提供一个字段—值对,可以把逻辑条件看作是一个不用自己写编辑器的常用条件。如何得到用户操作的结果呢?如果是自己组织的逻辑条件或者自定义的常用条件Panel,那肯定是产品组自己负责得取了。如果是用的默认的逻辑条件Panel,可以用DefaultLogicalEditor.getNormalObject()得到,并自己去组织数据了。Q8:如何插入自定义Tab到查询对话框?答:qcd.getQryCondEditor().getEditorTabbedPane().addTab("title",panel)即可。Q9:如何让用户只能够单选呢?答:在默认情况下,我们是允许参照多选的。如果想单选,则把操作符注册为==(双等号,中间没有空格)。即可Q10:如何查询值为空的字段呢?答:查询模板定义了“为空”操作符,有两种:1、只查询数据库中字段为null的,则需要把操作符注册为“isnull”;2、如果要查询字段为null或者字段值除了空格的字符串长度为0的,需要把操作符注册为“ISNULL”。同理,查询模板支持非空查询,对应的操作符为“isnotnull”和“ISNOTNULL”。Q11:模板数据加载后,如何根据某个字段值来对其他查询条件的属性做设置,如设置其他查询条件的值(联动),设置其他查询条件参照的where条件等?答:从前文我们可以看到,在加载模板数据时可以根据需要通过注册机制来完成对查询条件的设置,如默认值,参照的where条件等,一旦数据加载后,就需要通过查询模板的事件处理机制来对上述需求进行处理了。Q12:如果对于某些为空的字段,为了提高效率,用字符串替代之,但是启用数据权限后,查询模板附加的信息是codeisnullor…这种情况怎么处理?答:在调用模板时,调用TemplateInfo的setDatapowerNullStr(StringdatapowerNullStr)来设置代替空字段的字符串。这样拼出的sql为codeisnullorcode=‘datapowerNullStr’or………附录附一查询条件表中个字段含义查询模板的查询条件定义在pub_query_templet中,其对应的字段含义参见下表:数据库字段字段含义datatype数据类型,如字符,数值,参照。定义见IQueryConstantsif_immobility是否固定条件。(即不能编辑)if_must是否必输项if_default是否默认显示到模板上if_used是否为可选条件,即是否在候选条件树中出现if_datapower是否启用数据权限if_order是否排序字段if_autocheck仅对参照类型有效.表示参照的输入框能否接受一个"不存在"的值iscondition是否查询条件,如果为否既是逻辑条件disp_type/return_type适用参照类型.表示参照显示/返回的值是使用其编码,名称,还是PK,定义见IQueryConstantsopera_code操作符编码。每个操作符后带有一个@table_code字段所属表编码table_name表名称,非元数据查询候选条件根据该字段组织树状结构value字段默认值instrumentsql辅助sql,该字段的查询条件为该字段定义consult_code参照编码注1*:consult_code与数据类型datatype相关如果datatype=1,即整型可以用consult_code来设置取值范围,1、取值范围为[20,30],那么consult_code的值注册为20,30。2、取值范围为>20,那么consult_code的值注册为203、取值范围为<30,那么consult_code的值注册为@,30如果datatype=2,即小数可以用consult_code来设置小数点位数和取值范围,如果不设置默认为小数点后2位,consult_code的设置方式是以“,”为分隔符组成字符串,第一个数字表示小数点后位数,第二个表示最小值(无最小值用“@”代替),第三位表示最大值。如果datatype=5,即参照类型:(i)直接写参照名称.如部门档案(ii)<..>..自定义的参照Model类。如<nc.ui.ep.dj.DjbhRefModel>(iii){..}..为档案的名称,对应bd_bdInfo中定义的bd_name,如{人员档案}(iv)PK:...为档案的Pk,,对应bd_bdInfo中定义的pk,如PK:00010000000000000001如果datatype=6,即下拉类型:(i)首先明白几个前缀I,C,S的意义。它们表示所选的值!I:(index):表示返回值是数值型的索引,如0,1,2等;C:(char)表示返回值是字符型的索引,如’0’,’1’等;S:(String)表示返回值是下拉的内容,如”hello”等(ii)在(i)中的几个前缀后跟上X或者F意义不一样!它们表示显示名称X:表示多语。支持两种形如:CX,UC000-0001589=3和CX,UC000-0001589.前者最终显示的为多语定义的内容且返回值为=后面的数值或者是其对应的字符,后者从该模板的功能节点对应下的资源下去取多语。F:表示其对应数据来源于表pd_dd.(字段值列表).形如IF,bd_accbank,banktype表名/字段名。显示的时候,如果有多语定义,则从文件夹‘10083002’中读取其多语来填充下拉值。取值时候,如果IF,表示取szqz字段的int表示形式;如果CF,则表示取szqz字段的字符表示形式;如果为SF,则直接取自字段qzsm;(iii)v5.3针对新的查询模板新加!对于如果想从xh或者zfqz字段,取值,我们新建规则,使用与IF(CF,SF)组合,在原来的字段名后追加列名来表示,所取的值!如IF,bd_accbank,banktype,xh表示取对应xh列的值。(iv)所有的可能测试用例如下:各组中相同效果的推荐使用靠前的vo.setConsultCode("I,男,女");//return0,1;butnottranslate,sodisencouragevo.setConsultCode("C,男,女");//return'0','1'vo.setConsultCode("S,男,女");//return"男","女"vo.setConsultCode("I,男=4,女=8");//return4,8vo.setConsultCode("C,男=4,女=8");//return'4','8'vo.setConsultCode("S,男=male,女=female");//return"male","female"//return0,1;displayi18n(UPP10100-111),i18n(UPP10100-112)vo.setConsultCode("IX,UPP10100-111,UPP10100-112");//sameeffectasabovevo.setConsultCode("IX,UPT10080806-000014=男,UPT10080806-000017=女");//return'0','1';displayi18n(UPP10100-111),i18n(UPP10100-112)vo.setConsultCode("CX,UPT10080806-000014,UPT10080806-000017");//returni18n(UPP10100-111),i18n(UPP10100-112);displaysameasreturnvo.setConsultCode("SX,UPT10080806-000014,UPT10080806-000017");//ewei++//vo.setConsultCode("SX,UPT10080806-000014=1,UPT10080806-000017=2");则显示值为多语资源,返回值为=后的值,如果=后为非int型,返回索引vo.setConsultCode("SF,bd_produce,batchrule");//returnqzsmvo.setConsultCode("IF,bd_produce,batchrule");//returnszqzvo.setConsultCode("CF,bd_produce,batchrule");//returnchar(szqz)vo.setConsultCode("SF,bd_produce,batchrule,zfqz");//returnzfqzvo.setConsultCode("IF,bd_produce,batchrule,zfqz");//returnszqz.Ifirstvo.setConsultCode("IF,bd_produce,batchrule,xh");//returnxhvo.setConsultCode("CF,bd_produce,batchrule,xh");//returnchar(xh)vo.setConsultCode("SF,bd_produce,batchrule,xh");//returni18n(qzsm)注2*instrumentsql的使用方式:例如,我们定义一个查询条件编码为table.code,从界面上取值为’001’,那么如果我们在没有注册instrumentsql的情况下,得到的sql为table.code=’001’。如果我们把instrumentsql注册为‘selectidfromtablewhere???’,那么我们得到的sql是selectidfromtablewheretable.code=’001’(详见专题一)。附二系统函数列表查询条件的取值可以使用系统函数,带有#value#的为系统函数,列表如下:系统函数名称描述Sys_Account会计期间Sys_Year当前年份Sys_Month当前月份Sys_Date当前日期Sys_Operator当前操作员Sys_department当前部门Sys_CurrCorp当前公司Sys_daysBefore_i当前日期前i天Sys_monthsBefore_i当前月前i月Sys_DeptWithChild当前部门及其下级门专题一:定制自定义SQL查询模板实质上是将一条一条的查询条件,通过逻辑关系和嵌套组织成完整查询条件。而每一条查询是由一个Filter定义的。而查询模板默认实现的sql语句往往不能完全满足业务组的需要,这就需要项目组自定义SQL,如何自定义SQL呢,在讲清楚这个问题之前,先说明几个基本概念。1、BasicSql由查询模板生成的单条查询条件为filed_code+operator_code+value,如下面定义的条件其返回的sql形如date=‘2007-01-01’。在这里我们称之为BasicSql,可以通过IFlter的getBasicSql()得到。2、CombinedSql本版查询模板对查询条件按照一定条件进行了合并优化,即符合合并条件并且在同一个逻辑操作符下的Filter,先进行合并,再查询。判断Filter是否能够合并,使用Filter中的booleancombinable(IFilterfilter)方法判断,查询模板默认将FilterMeta中instrumentedsql(用于固定自定义sql生成,后文详细介绍)属性相同的Filter认为可合并。如如果上述两条件可以合并,那么在生成SQL前,进行条件合并生成一个Filter,我们假设这个Filter叫做CombineFilter,那么CombineFilter的SQL...