2012年6月26日星期二

ADF_148:Table 组件使用指南之十八:自定义Date类型字段过滤器

运行环境:JDeveloper 11.1.2.1.0 + Oracle Database 10g Express Edition 10.2.0.1。

Date类型的字段,如果使用默认的Table的Filter功能,其运行效果如下:

样例Project请参考《Table 组件使用指南之十一:列字段过滤功能》。
但是在实际使用中,遇到一个问题:当日期数据包含时分秒时,数据过滤不出来。
比如,把EMPLOYEE_ID = 200的日期数据改成带时分秒的格式:
UPDATE "HR"."EMPLOYEES" SET HIRE_DATE = TO_DATE('17-JUN-1987 19:32:36', 'DD-MON-YYYY HH24:MI:SS') WHERE EMPLOYEE_ID = 200;
commit;

然后,使用Filter功能查询日期为17-JUN-1987的记录,发现查询结果没有包括EMPLOYEE_ID = 200的记录。

测试完毕后恢复EMPLOYEE_ID = 200的原来的日期格式:
UPDATE "HR"."EMPLOYEES" SET HIRE_DATE = TO_DATE('17-JUN-87', 'DD-MON-RR') WHERE EMPLOYEE_ID = 200;
commit;

感觉这个问题是个BUG,默认的Date Filter功能既然不支持,那么就自定义吧。
自定义包括自定义查询组件,以及如何获取和处理Filter条件。

重要步骤说明:
1. 定义一个ViewCriteria,并且定义两个参数作为Filter条件

这里还可以指定查询的范围:是Database,还是缓存,还是二者兼而有之。
2. 修改页面代码
(1)在HireDate的filter facet中增加两个日期组件,查询在一段时间范围的记录。

<af:column sortProperty="#{bindings.EmployeesView1.hints.HireDate.name}" filterable="true"
sortable="true" headerText="#{bindings.EmployeesView1.hints.HireDate.label}" id="c6">
<f:facet name="filter">
<af:panelGroupLayout id="pgl2" layout="horizontal">
<af:panelLabelAndMessage label="From: " id="plam1">
<af:inputDate id="id2" value="#{vs.filterCriteria.HireDateStart}">
<af:convertDateTime pattern="#{bindings.allEmployees.hints.HireDate.format}"/>
</af:inputDate>
</af:panelLabelAndMessage>
<af:spacer width="5" height="5" id="s1"/>
<af:panelLabelAndMessage label="To:" id="plam2">
<af:inputDate id="id3" value="#{vs.filterCriteria.HireDateEnd}" required="false">
<af:convertDateTime pattern="#{bindings.allEmployees.hints.HireDate.format}"/>
</af:inputDate>
</af:panelLabelAndMessage>
</af:panelGroupLayout>
</f:facet>
<af:outputText value="#{row.HireDate}" id="ot6">
<af:convertDateTime pattern="#{bindings.EmployeesView1.hints.HireDate.format}"/>
</af:outputText>
</af:column>

说明:vs.filterCriteria.HireDateStart和vs.filterCriteria.HireDateEnd就是两个Filter条件。
你可以在这里直接创建任意名称的参数,不需要在其它地方定义,所有参数将会保存在一个map对象中。
(2)修改Table的 queryListener,从默认的"#{bindings.EmployeesView1Query.processQuery}" ,改成"#{myBackingBean.employeeQueryListener}",即指向一个Managed Bean。

3. 完整的Managed Bean代码

package view;

import java.util.Map;

import oracle.adf.view.rich.event.QueryEvent;
import oracle.adf.view.rich.model.FilterableQueryDescriptor;

import oracle.jbo.ApplicationModule;
import oracle.jbo.VariableValueManager;
import oracle.jbo.ViewCriteria;
import oracle.jbo.ViewCriteriaManager;
import oracle.jbo.ViewObject;

import view.util.ADFUtils;
import view.util.JSFUtils;


public class MyBackingBean {
public MyBackingBean() {
}

public void employeeQueryListener(QueryEvent queryEvent) {
FilterableQueryDescriptor fqd = (FilterableQueryDescriptor)queryEvent.getDescriptor();
Map map = fqd.getFilterCriteria();
Object hireDateStart = map.get("HireDateStart");
Object hireDateEnd = map.get("HireDateEnd");

ApplicationModule am = ADFUtils.getDCBindingContainer().getDataControl().getApplicationModule();
ViewObject vo = am.findViewObject("EmployeesView1");
ViewCriteriaManager vcm = vo.getViewCriteriaManager();
ViewCriteria vc = vcm.getViewCriteria("EmployeesViewCriteria");
VariableValueManager vvm = vc.ensureVariableManager();
vvm.setVariableValue("bv_hireDateStart", hireDateStart);
vvm.setVariableValue("bv_hireDateEnd", hireDateEnd);

//remove temporary attributes as they don't exist in the business service and would cause a NPE if passed with the query
map.remove("HireDateStart");
map.remove("HireDateEnd");

JSFUtils.invokeMethodExpression("#{bindings.EmployeesView1Query.processQuery}", Object.class, QueryEvent.class,
queryEvent);

// put values back so search filter is not empty
map.put("HireDateStart", hireDateStart);
map.put("HireDateEnd", hireDateEnd);
}
}

说明:基本逻辑是获取Filter参数后,赋值给ViewCriteria中绑定变量。

4. 运行效果
可以看出,带时分秒的记录也被正确地查出来了,说明通过ViewCriteria得到的查询结果比Table默认的Filter功能更准确。


Project 下载:ADF_Table_Filter(3).7z

参考文献:
1. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/16-custom-table-filter-169145.pdf
2. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/30-table-filter-queries-169172.pdf
3. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/59-table-filter-by-data-range-176653.pdf
4. http://dkleppinger.blogspot.jp/2011/09/how-to-ignore-time-component-of-date.html
5. http://msdn.microsoft.com/zh-cn/library/ms186724.aspx

没有评论: