概述
目录
第一部分 插入新行前的初始化
1 仅插入型VO的初始化
2 插入查询VO的初始化
第二部分 执行查询前的初始化
1 避免无条件查询
2 避免多余的查询
正文
第一部分 插入新行前的初始化
在处理插入初始化之前,我们必须确定一件事情,就是当前我们要处理的这个VO,它是只用作插入操作呢,还是即用作插入又用作查询操作。比如一个EmployeeCreateVO,这个VO仅仅在创建新员工的页面使用,不用做其他用途,那么我们认为它是一个只做插入操作的VO,反之,它就是一个即查询又插入的VO.理清楚这一点,对合理初始化VO很重要。
1仅插入型的VO的初始化
我们可以利用如下代码:
//检查VO是否有行,如果有行了,我们就不用执行括号里的语句了。vo.getFetchedRowCount()是检查当前缓存中VO的行数,包括新插入的行,它不执行数据库查询,仅仅检查内存中已经取出来的行。如VO已经被插入过行了,那么getFetchedRowCount肯定大于0,就无需再调用setMaxFetchSize了
if (vo.getFetchedRowCount() == 0) {
//此方法是设置VO的每次查询行数的上限,但是如果参数为0的话,此方法会设置mPreparedForExecution标识为TRUE。这个标识是OAViewObjectImpl的一个成员变量,表示VO是否准备好执行查询,初始值是FALSE。当VO执行了executeQuery()之后,该标识值也会被设为TRUE。
vo.setMaxFetchSize(0);
}
// 执行插入操作
Row row = vo.createRow();
vo.insertRow(row);
//遵循代码标准M69,在所有新插入的行后立即将起设置为STATUS_INITIALIZED状态,让此行处于脱管状态,不参与事务提交,不参与验证,直到在页面上对这行数据进行更新,然后OA框架自动把状态设回为STATUS_NEW,以重新参与事务和验证。
row.setNewRowState(Row.STATUS_INITIALIZED);
有时候我们会遇到这个错误:“违反了 OA 钝化结构编码标准。未正确准备全名为EmployeeAM.EmployeeFullVO1 的视图对象以供插入行。必须先调用视图对象中的setMaxFetchSize(0) 或executeQuery()(或最终执行视图对象查询的任何等效方法),然后才能插入新行。”
我估计是OAF框架在遇到插入行的时候,会检查当前VO有没有行,如果没有行,会检查在这句代码前面是否执行了executeQuery()或setMaxFetchedSize(0)语句(而不是检查mPreparedForExecution的值是否为TRUE),如果没有执行这样的语句,那么就报告违反钝化编码标准。当然这只是我的个人猜测,仅供参考。
对于只包含瞬时属性的VO,为了避免OAF中的一些已知的BUG,我们在对其进行初始化的时候最好像下面这样编写代码:
if (vo.getFetchedRowCount() == 0) {
vo.setMaxFetchSize(0);
vo.executeQuery();
... // Insert rows into the view object.
}
2带数据库查询的VO的初始化
首先,我们必须注意,在这种既用于查询又用于插入的VO情况下,我们必须先执行executeQuery(),然后再insertRow(),否则会导致一些钝化上的问题。
提示1:
总的来说,尽量为“创建**”或“插入**”型页面单独创建一个VO,比如单独创建一个创建员工的VO,EmployeeCreateVO.
提示2:
如果实在需要插入和查询或更新都公用一个VO,那么在插入前,应该给executeQuery加上条件。
if (!vo.isExecuted()){
vo.executeQuery();
// 或者调用vo.initQuery(..),以便根据你自己WHERE条件进行查询。
}
Row row=vo.createRow()
…其他初始化操作
注意:根据我个人经验,由于mPreparedForExecution标识变量并不会在rollback()后变为false,会造成未执行executeQuery()就进行insertRow()操作,那么OA框架就会报告“违反了OA 钝化结构编码标准。未正确准备全名为 EmployeeAM.EmployeeFullVO1的视图对象以供插入行。必须先调用视图对象中的 setMaxFetchSize(0) 或executeQuery()(或最终执行视图对象查询的任何等效方法),然后才能插入新行。”,所以在进行插入操作前,通过vo.isPreparedForExecution来作为判断条件不是最好的选择,可以选择用vo.isExecuted来代替。
第二部分 执行查询前的初始化
1避免无条件查询
一般情况下,我们可以使用下面的方法来避免无条件执行查询操作
if (!vo.isPreparedForExecution()) {//带条件执行查询操作
vo.executeQuery();
// 或者调用vo.initQuery(..),以便根据你自己WHERE条件进行查询。
}
无条件执行查询操作会导致一些事务状态的丢失,比如,对瞬时属性(transient view objectattributes)数据的更新会丢失,VO的current Row和currentRange会被重设。这也就从一定解释了“翻页后在有删除确认对话框的页面中无法删除行的案例”,具体参考我的另一篇文章《翻页后在有删除确认对话框的页面中无法删除行的案例》。
但是,有几种情况你不应该给查询加上条件:
1.你的页面是只读的,你不在乎VO的事务状态,你只希望每次渲染页面的时候都能看到数据库中的最新数据。
2.如果这个查询是在processFormRequest中调用的,例如,页面上有一个“GO”按钮,希望点击的时候查询出满足我需要的数据,那么这个时候也不要给他加上面的条件。因此,我们可以这样理解,上面的“带条件执行查询操作”仅用于在processRequest中对页面包含的VO的数据进行初始化操作。
3.加了这个条件后,在保持同一个AM的范围内,这个vo只被查询一次,以后不会再被查询,如果想重新执行查询,得到最新的数据,那么需要释放AM。
对于下钻页面(Drilldown TargetPage),比如搜索结果页面中点击员工姓名下钻到员工的详细信息,我们也不能依赖于isPreparedForExecution的判断,它太容易返回true了,以至于我们的查询得不到执行,我们更喜欢用vo.findByKey()这个方法,这个方法是根据VO下面的EO主键来查询,首先会检查缓存中有没有这条数据,没有才去执行数据库查询。注意,下钻页面的VO和搜索页面的VO最好不要使用同一个,以免下钻后,影响搜索页面的状态。
public void initDetails(Number employeeNumber){
EmployeeFullVOImpl vo = getEmployeeFullVO1();
Number[] keys = { employeeNumber};
Row[] rows = vo.findByKey(new Key(keys), 1);
// findByKey不会改变currentRow指针,所以需要我们手动去更改,否则页面上不会显示值。
if ((rows != null) &&(rows.length > 0)) {
vo.setCurrentRow(rows[0]);
} } // end initDetails()
2避免多余查询
涉及个性化,暂不讨论
最后
以上就是小巧乌龟为你收集整理的OAF VO初始化分析的全部内容,希望文章能够帮你解决OAF VO初始化分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复