dorado 常用
如果要设置模糊查询, 一般要在QueryCommand中这样写:
var name = dsQuery.getValue("NAME"); var parameters = command.parameters(); if (name) { parameters.setValue("NAME", "%" + name + "%") }
dataset如果没有分页的话, 默认一次是只取100条, 这也意味着如果记录超过100条就要考虑分页了, 如果我们不希望分页但是记录又操作了100条的话, 这需要将pageSize设置为-1
对于SQLDataset来说, orginTable属性是必须设置的, 这个比较奇怪, 我觉得这个orginTable只是对数据的修改才会有效, 虽然通过UpdateCommand做了提交,但是如果没有设置originTable就不应该做修改操作, 但是dorado内部却没有这么做, 所以这里除了无奈的设置originTalbe属性之外,还要借助Record.setState(none)的方式来避免做更新操作
还有一个可能会经常碰到的奇怪的地方,就是如果数据库中用一个char(1)来表示一个boolean值,在dataset中不能直接将其属性设置为boolean,而是必须设置为string, 然后手工设置editerType为checkbox, 而且在编辑的时候还需要在编辑器的onSetValue()事件中写如下代码:
checkBox.checked = dsEntity.getValue("admin") == 1 ? true : false;否则打勾选中跟dataset之间的同步会有问题
单表操作是一个系统中会经常碰到的问题, 它简单,繁琐, 重复, 堪称无聊中的无聊. 因此我们在处理这种操作界面的时候通常会考虑到尽可能的重用, 因为没法做到继承, 所以我们只好不停的copy&paste, 当然通过插件提供的模板也可以简化我们的工作, 不过我在开发中更喜欢copy&paste, 毕竟做一个比较通用的模板也不是分分钟就能搞定的. 那么如何保证我们的copy&paste更有效, 改动更少呢? 我发现在在命名上有一定的技巧, 就是对各种通用的dataset和control采用泛型化的命名方式, 比如对一个公告表的单表操作, 在dataset上可以命名为dsEntity, 对于数据的列表显示可以命名为tblEntity, 编辑AutoForm可以命名frmEntity如此等等, 这样在对这些id进行引用时可以保证具有一定的稳定性, 不会因为换成另外一个单表的维护配置文件, 而需要对这些常用的id进行修改, 这样做多了, 模板自然而然就形成了. 因此我不推荐一开始就去建一个模板, 而是应该在应用中通过不断提炼总结而得到一些通用的模板
subwindow不要在view.xml文件中创建, 直接在jsp中定义, 否则在使用show(true, true)打开subwindow的时候出现无法居中的问题
通过远程调用不需要使用将WrappedDataset转换成具体的dataset(使用updatecommand执行远程调用时需要转换), 但是在复写init之类的方法则需要这样做, 即在ViewModel中需要将Dataset转换成指定类型的Dataset需要这样做:
Dataset dsRole = this.getDataset("dsEntity"); DatasetWrapper dr = (DatasetWrapper) dsRole; SqlDataset ds = (SqlDataset) dr.getWrappedDataset();
在复写initDatasets方法的时候,需要注意通过getState()判断当前的请求的状态,因为在执行updatecommand之类的command,也会调用initDatasets方法
给某个日期字段设置为当前日期的写法
var current = dsQuery.getCurrent(); current.setValue("datetime", "${Util.getDate('yyyy-MM-dd HH:mm:ss')}");
或直接在dataset的指定field设置defaultValue属性为${Util.getDate("yyyy-MM-dd")}
对于formdataset来说,通过listener来为其加载数据(比如使用dataset.insertRecord()方法),在对应的的autoform中是不会取得数据的
dorado与报表
交叉表只能放在summery区,否则会出现
net.sf.jasperreports.engine.JRRuntimeException: Error incrementing crosstab dataset
java.io.InvalidClassException: net.sf.jasperreports.engine.base.JRBaseReport; local class incompatible: stream classdesc serialVersionUID = 607, local class serialVersionUID = 608
错误原因是 jasperreports.jar 版本不统一
jrxml complie to jasper 是在 iReport 中完成的,然后直接把 .jasper 拷贝 到应用中使用,一直抛错,后来发现是 iReport 和应用中使用的 jar 版本不一致,
iReport :jasperreports-1.1.1.jar
应用:jasperreports-1.2.0.jar
统一为 jasperreports-1.2.0.jar 就可以了
如果要使用主从更新的话, 那么要取消掉主从之间的外键约束,否则在同时保存主从表的时候会出现违反主从外键约束的异常
通过在dataset的listener中使用insertRecord()添加一条记录的时候,记录的状态是none,然后放到前台来修改,最终提交的时候注意设置该记录的状态为new,因为该记录的状态仍然为none
在后台通过DBStatement插入记录的时候,如果有字段为date类型,那么插入的日期默认情况下是不带日期的(其他不清楚,反正oracle下是如此),要使得数据带日期,需要这样做:
Variant variant = new Variant(); variant.setDataType(12); variant.setValue(new Date()); params.setVariant(fieldName, variant);
在staticTable中给日期字段设置显示格式的pattern写法:
true和false转男女的写法:
格式化日期的表达式:
el表达式在server运行,一律是java对象。
record就是Record对象,Util是com.bstek.dorado.common.rtexpr.impl.ExpressionUtils
在dorado写sql的时候,参数名最好采用下划线的方式命名, 这样更简洁
如果需要实现alert(message) + AbortException的功能, 请这样使用:
throw new DoradoException(message);
dbstatement.close请谨慎使用, 因为close是关闭连接, 事务结束, 如果有多个操作的时候, 可能因为是在多个事务中操作而导致数据不一致
对于customdropdown来说, 从dropdown向外面传递选中的数据, 需要在指定的地方这样写:
DropDown.closeFrame(dsEntity.getCurrent());
在外面接收需要在dropdown的onSelect事件中这样写:
if (selectedObject) { var params = dsRichFormItem.parameters(); var formId = selectedObject.getValue("ID"); params.setValue("paymentFormId", formId); params.setValue("formId", formId); dsRichFormItem.flushData(); } return true;
向customdropdown传递参数需要在ViewModel中通过指定路径后面添加参数来实现:
protected void initControl(Control control) throws Exception { super.initControl(control); if (getState() == STATE_VIEW && control.getId().equals("lstEmployee")) { CustomDropDown lstEmployee = (CustomDropDown) control; lstEmployee.setPath(lstEmployee.getPath() + "?employeeId=" + getInitiatorId()); } }
在command中使用dsAssign.postRecord()验证语句时要这样用:
if (dsAssign.postRecord()) { var employeeId = dsAssign.getValue("employeeId"); command.parameters().setValue("employeeId", employeeId); command.parameters().setValue("accountId", dsAssign.getValue("accountId")); }else{ return false; }
否则在出错的时候也会提交
除了可以使用autosqldataset来做自动提交之外, 还可以使用sqldataset来做自动提交, 由于sqldataset具有更大的灵活性, 所以一般都采用之, 要使得能提交, 这里需要做一些设置, 一个是要设置dataset的originTable以及keyFields属性, 以及设置每一个要更新字段对应的数据库中表字段名
在设置dataset的只读, 可写属性之后记得refreshControl, 否则会有一些延迟的问题, 比如这样写:
dsEntity.getField("employee_name").setReadOnly(false); dsEntity.refreshControls();
在使用QueryCommand+FormDataset做查询的时候, 有时候多次查询, 前一次查询的参数不会清除, 仍然会带到下一次查询, 这里我们需要在command的onSuccess事件中写这样的代码:
cmdQuery.parameters().clear();
在使用sqldataset做模糊查询的时候, 要模拟autosqldataset的支持逃逸功能, 需要象这样做:
比如在sql中有这样一句:
a.name like :accountName
那么需要写这样的一个parameter:
<Parameter dataType="" name="accountName" value="%%"/>
在使用了FormDataset+QueryCommand来做查询操作的时候, 有时候url后面存在参数与FormDataset中字段同名的话, 会造成自动赋值的问题, 解决的办法就是将FormDataset的autoLoadData设置为false
对于datetime的处理, 有时候需要让日期加上时分秒, 则必须将绑定字段设置为datetime类型, 但是又希望必须以string的方式来取该datetime字段, 典型的情况就是QueryDataset+QueryCommand的情况, 这时需要将日期字段设置为string类型, 绑定一个DataDropDown, 并给DateDropdown的onselect事件中写如下的脚本:
editor.getRecord().setValue(editor.getField(), formatDate(selectedObject, "yyyy-MM-dd HH:mm:ss"));