Dorado 5 : 1.3.2.UpdateCommand(更新命令) (RF2)

简述

Dorado页面中的数据使用dataset管理,而通过页面上各种展示dataset数据的组件进行操作,或由用户维护其中的数据,或由用户选择其中的数据,之后再将这些数据传递到服务器端的业务逻辑层处理。在dorado中使用UpdateCommand封装这种操作,开发时开发人员只需要在UpdateCommand中指定需要提交的Dataset,并指定服务器的接收对象和接收的处理方法。UpdateCommand执行时属于页面无刷新的数据提交,可同时指定一到多个客户端的dataset对象批量提交,支持事务管理模式,支持异步处理机制。
另外需要注意到UpdateCommand提交存在的一个默认潜规则,在说明这个规则之前,我们先看看dataset对象,看下图使用DataTable展示dataset数据的图:

图表 12 Submit Scope
Dataset是一个包含多行数据的一个大对象,如共有100条记录,如果UpdateCommand对象指定要提交该Dataset对象,则每一次执行我们是不是要将100条记录全部提交到服务器呢?实际上是完全没有必要的,对于逻辑处理层而言,通常情况下逻辑层只是关心要处理的数据,例如用户选择了哪些行,提交这些选中数据即可,或用户在这100条记录中修改的那些记录,新增的是什么记录,删除的是什么记录等等,实际上开发人员只需要将真正需要后代逻辑层处理的信息提交过去即可,这样也有利于减少网络数据的传输量,从而提高整个系统的响应能力和优化网络情况。于是UpdateCommand在指定要提交的dataset对象的同时还可以同时指定该dataset的提交范围:submitScope,通过这个属性我们可以指定dataset提交时将内部的那一部分数据发送到给逻辑层,目前已有的方式有:all-change,all,selected, current分别用于指定提交不同的范围数据:

submitScope

说明

all-change

提交当前dataset中所有被改动过的记录,包含新增,已删除但还没有提交以及被修改过的记录

all

提交当前dataset中的所有记录,包含已经被删除和不可见的记录

selected

提交当前dataset中select字段值为true的记录(select字段的解释参考<<dorado 5 用户指南.doc>>的select字段部分)

current

提交dataset当前光标所在的记录(当前光标概念参考<<dorado 5 用户指南.doc>>的dataset当前光标概念的解释部分)

all-visible

提交所有可见的记录(即不提交已删除的记录和被onFilterRecord事件过滤掉的记录)

数据提交时UpdateCommand会自动的根据该属性确认dataset中是否有符合范围的数据,如果没有,UpdateCommand就不再向Server发出任何请求。由于UpdateCommand这个默认规则会引起一些现象,例如默认的submitScope为all-change,如果用户在客户端并没有修改任何的数据,而直接执行UpdateCommand,这时候UpdateCommand根据自己的根据submitScope判断后会发现没有任何符合的数据可以提交,就不会向服务器发出请求。页面的表现就是该命令执行后无任何合理的反应。这是开发人员在设计时需要注意的。

使用

基本使用

一个典型UpdateCommand的定义代码如下:

<Control id="cmdRaiseSalary" type="UpdateCommand" method="raiseSalary">
<DatasetInfos>
<DatasetInfo dataset="dsEmployee" submitScope="current" />
</DatasetInfos>
<Parameters />
</Control>

其中DatasetInfos节点用于指定需要提交的客户端的dataset对象,通过submitScope指定提交dataset对象的提交范围。上面代码中定义为"current"表示只提交datasetEmployee的当前记录。
而command的method属性用于指定调用服务器接受类的指定方法的方法名(默认为视图模型中的方法名,如果使用Marmot框架开发也可以为Spring中Bean的方法名,Marmot的提交建议使用MarmotUpdateCommand,详细内容参考MarmotUpdateCommand)。
UpdateCommand被执行时会自动将DatasetInfos中定义的记录集按照submitScope的范围查询需要提交的数据信息并收集好,按照method指定的方法向指定服务(Services)发出请求并传送这些数据。
服务器接收这些数据的对象默认为视图模型的实现类,运行期间由dorado自动创建,并根据method利用反射机制调用该方法,如果不指定method,系统默认调用视图模型的doUpdate方法,在method指定方法内部可以访问客户端提交过来的数据,范例如下:

public void raiseSalary(ParameterSet parameters, ParameterSet outParameters)
throws Exception {
Dataset dsEmployee = getDataset("dsEmployee");
if (dsEmployee.getCurrent() != null) {
float salary = dsEmployee.getFloat("salary") + 500;
dsEmployee.setFloat("salary", salary);
MessageHelper.addMessage(
DoradoContext.getContext(),
"[" + dsEmployee.getString("employee_name") + "]已加薪至"
+ salary + "!");
}
super.doUpdateData(parameters, outParameters);
}

通过视图模型实现类提供的getDataset()方法传入一个dataset的id获得客户端提交过来的数据,并且以dataset结构封装。服务器端dataset与客户端的dataset具有相同的结构,并且提供了非常丰富的接口便于开发人员访问和使用它。
根据UpdateCommand的Method设定,可以在视图模型实现类中定义一个方法响应UpdateCommand的请求。详细说明请参考视图模型实现类的使用。

参数使用

另外UpdateCommand还提供了parameters()参数集合,便于在提交的时候添加一些用户自定义的信息,使用方式如:

<Control id="cmdDelete" type="UpdateCommand" method="deleteContract">
<DatasetInfos>
<DatasetInfo dataset="dsContract" submitScope="current" />
</DatasetInfos>
<Parameters>
<Parameter name="param1" value="D11" />
</Parameters>
</Control>

也可以在js脚本中动态设定,如:

cmdUpdate.parameters().setValue("parame1", "D11");
cmdUpdate.execute();

事件处理

当UpdateCommand命令成功执行或有系统异常抛出时,它提供不同的事件处理,便于开发人员根据执行结果做不同的处理,例如:利用UpdateCommand的onSuccess以及onFailure方法给用户提供提示信息,如在onSuccess中写入js代码:

alert("保存成功!");

在onFailure中写入代码:

alert("保存失败!");

关于outParameters()的作用

UpdateCommand的视图模型方法调用,允许开发人员在视图模型的实现类中返回一些自定义的信息,并且可以在客户端通过脚本从UpdateCommand的outParameters()参数集合中获取这些信息。
范例:
视图模型实现类代码:

public void raiseSalary(ParameterSet parameters, ParameterSet outParameters)
throws Exception {
Dataset dsEmployee = getDataset("dsEmployee");
if (dsEmployee.getCurrent() != null) {
float salary = dsEmployee.getFloat("salary") + 500;
dsEmployee.setFloat("salary", salary);

outParameters.setString("msg",
"[" + datasetEmployee.getString("employee_name") + "]已加薪至"
+ salary + "!");
}
super.doUpdateData(parameters, outParameters);
}

command调用命令:

var result = cmdRaiseSalary.execute();//根据result判断是否调用成功
if (result) alert(cmdRaiseSalary.outParameters().getValue("msg"));

常用技巧

动态添加参数

参考QueryCommand的动态添加参数

如何不受submitScope限制

UpdateCommand中submitScope属性会影响UpdateCommand是否向视图模型实现类发出数据保存请求,为了避免该请求受submitScope限制,可以通过UpdateCommand的alwaysPerform属性加以控制,设定为true,则无论dataset中的数据如何,UpdateCommand总能向视图模型的实现类发出请求。

主从表提交

UpdateCommand中同时包含了多个dataset对象,而这些对象在逻辑上存在主从关系,例如采购合同和产品。一个合同可以采购多个产品,图例:

图表 13 合同维护界面
在上图中的合同维护界面中,界面主要分上下两块区域,上面的AutoForm主要负责维护合同基本信息,而下面的DataTable主要维护合同的采购产品明细信息。当这个页面执行保存操作的时候,对于服务器的逻辑层而言是一定要取得合同基本信息的。否则采购产品信息就无法保存到相关的合同中,而UpdateCommand我们的定义如下:

<Control id="cmdSave" type="UpdateCommand" method="saveAll">
<DatasetInfos>
<DatasetInfo dataset="dsContract" submitScope="all-change" />
<DatasetInfo dataset="dsItems" submitScope="all-change" />
</DatasetInfos>
<Parameters />
</Control>

如果采用默认的提交机制,当用户不对dsContract对象作修改操作,dsContract中的信息就不会提交到服务器端的逻辑层中。为了解决这个问题,我们只要稍稍调整一下dsContract的submitScope属性即可:

<Control id="cmdSave" type="UpdateCommand" method="saveAll">
<DatasetInfos>
<DatasetInfo dataset="dsContract" submitScope="current " />
<DatasetInfo dataset="dsItem" submitScope="all-change" />
</DatasetInfos>
<Parameters />
</Control>

将submitScope调整为current,则UpdateCommand执行时总是会将dsContract中的当前记录提交到逻辑层代码中。
以上的用例中submitScope的设置只是一种处理方式,在实际应用中,这种主从表的数据提交,要根据逻辑处理层的需要而灵活的设定。

异步处理

参考QueryCommand的异步处理

多选提交

UpdateCommand还提供了记录的多选提交支持,实现这个功能首先得在dataset中添加boolean类型的select字段,该字段的使用方式参考ViewDataset中的关于select字段的说明,多选提交在很多系统中都大量存在,如下图的多选删除,原理上就是将选中的行提交到逻辑层作删除操作:

图表 14 多选删除界面
对于一个拥有select字段的dataset对象,当它通过UpdateCommand提交时,我们可以通过如下方式指定提交dataset中select字段为true的记录:

<Control id="cmdDeleteSelection"
type="UpdateCommand" method="deleteSelection">
<DatasetInfos>
<DatasetInfo dataset="dsEmployee" submitScope="selected" />
</DatasetInfos>
<Parameters />
</Control>

很简单,指定dsEmployee对象的submitScope为selected即可。
这样java逻辑层就能获得这些select为true的记录,执行业务操作,另外UpdateCommand还提供了多选提交操作的其他一些特性:

<Control id="cmdDeleteSelection"
type="UpdateCommand" method="deleteSelection">
<DatasetInfos>
<DatasetInfo dataset="dsEmployee"
submitScope="selected"
clearSelectionOnSuccess="true"
deleteSelectionOnSuccess="true"
flushDataOnSuccess="true" />
</DatasetInfos>
<Parameters />
</Control>

以上三个属性都是用来指定UpdateCommand执行成功后的回调处理:
clearSelectionOnSuccess:命令执行成功后清空选中记录的select信息,设置为false;
deleteSelectionOnSuccess:命令执行成功后删除客户端dataset缓存的记录中select为true的记录;
flushDataOnSuccess: 命令执行成功后清空客户端dataset中包含的所有记录,并从服务器端重新加载数据(一般用于接受UpdateCommand命令请求的逻辑层代码较为复杂,逻辑处理结束后,当前dataset中的信息已经无法准确的反应系统的真实情况,而必须使用flushData()方法重新获取时采用);

动态编程

在服务器段动态生成UpdateCommand

protected void initControls() throws Exception {
super.initControls();//系统默认函数,注意保留
UpdateCommand cmdUpdate = (UpdateCommand)createControl("UpdateCommand", " cmdUpdate");
cmdUpdate.addDatasetInfo("dsEmployee","all-change");//定义要提交的dataset
cmdUpdate.setMethod("raiseSalary");
}

使用视图模型实现类提供的createControl方法创建UpdateCommand对象,注意第一个参数用以指定组件的类型,第二个参数指定新建对象的id

在服务器端获得View(视图模型)中定义的UpdateCommand,并动态它的属性

protected void initControls() throws Exception {
super.initControls();//系统默认函数,注意保留
UpdateCommand cmdUpdate = (UpdateCommand)getControl("cmdUpdate");
cmdUpdate.addDatasetInfo("dsEmployee","all-change");//定义要提交的dataset
cmdUpdate.setMethod("raiseSalary");
}

在上面的代码中可以看到通过实现类提供的getControl函数获得我们需要的组件对象,所需要的就是给它一个UpdateCommand对象的id,注意开发时我们建议您直接在View的设计中添加一个空UpdateCommand组件,这样我们就可以在initControls方法中通过getControl方法获得这个空的UpdateCommand对象,并利用该对象提供的API进行各种设定和初始化的工作,如UpdateCommand的addDatasetInfo(), setMethod()方法。

主要属性说明

基本属性参考ListDropDown中的属性说明

属性

说明

action

命令执行时调用server的action(如: struts ,webwork, spring mvc等的action机制)
目前不建议使用,建议直接使用Marmot框架处理机制实现

alwaysPerform

是否总是提交,默认情况下UpdateCommand根据DatasetInfos节点中dataset的submitScope的设定是否收集到需要提交的数据决定是否真正向服务器端发出保存的请求,如果这个alwaysPerform属性设定为true,则无论UpdateCommand中是否有满足条件的数据,UpdateCommand都一定会向视图模型发出请求要求调用其中的相关处理方法。

async

是否支持异步执行,默认为false

method

指定接收该请求的视图模型实现类的方法名

reduceReturnInfo

表示简化提交处理的服务端返回信息,用于优化那些不需要关注提交记录在服务端的状态和数据变化的大数据量提交操作。

showLoadingTip

执行命令时是否弹出信息提示框

transactionMode

提交的事务机制(通过dorado提供的jdbc数据链接提交时有效)
not_supported 不支持事务
supports 支持事务,但是本身不会启动新的事务
required 要求事务管理,如果当前事务未启动,则启动一个新事务
requires_new 要求必须启动新的事务为该请求提供服务

UpdateCommand中还包含DatasetInfo子对象,该对象用于定义要提交dataset的提交特性, DatasetInfos主要属性说明

属性

说明

clearSelectionOnSuccess

提交成功后清空select字段的选中状态

dataset

被提交的dataset对象

deleteSelectionOnSuccess

提交成功后删除select字段打勾的记录

flushDataOnSuccess

提交成功后自动调用dataset的flushData刷新数据

submitScope

dataset的提交范围
all:提交客户端缓存的dataset中的所有记录
all-change:提交客户端缓存的dataset中的所有被修改过的记录
current:提交dataset的当前记录
selected:提交dataset中select字段的值为true的所有记录

主要事件说明

基本事件说明参考QueryCommand的事件说明