运行环境: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中增加两个日期组件,查询在一段时间范围的记录。
说明:vs.filterCriteria.HireDateStart和vs.filterCriteria.HireDateEnd就是两个Filter条件。
你可以在这里直接创建任意名称的参数,不需要在其它地方定义,所有参数将会保存在一个map对象中。
(2)修改Table的 queryListener,从默认的"#{bindings.EmployeesView1Query.processQuery}" ,改成"#{myBackingBean.employeeQueryListener}",即指向一个Managed Bean。
3. 完整的Managed Bean代码
说明:基本逻辑是获取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
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
http://maping930883.blogspot.com/2012/08/adf148table-date.html