在这篇文章中,我想跟进我以前关于Oracle集合数据类型的文章 ,并且我将集中精力使用af:table组件中的oracle.jbo.domain.Array属性。
因此,在我的数据库中,我具有以下SQL类型:
create or replace type varchar2_array_type as table of varchar2(200)
我有下表:
create table testarray (
SomeField Number,
ArrValue VARCHAR2_ARRAY_TYPE)
nested table ArrValue store as arrvalue_tab return as value;
ADF BC模型中有一个基于testarray表的实体:
属性Arrvalue的数据类型为oracle.jbo.domain.Array。
绑定容器中有一个相应的属性绑定:
<attributeValues IterBinding="VTestarrayIterator" id="Arrvalue"><AttrNames><Item Value="Arrvalue"/></AttrNames></attributeValues>
显示此属性值的最简单方法如下:
<af:table value="#{bindings.Arrvalue.inputValue.array}" var="row" id="t1"><af:column sortable="false" headerText="Array Values" id="c1"><af:inputText value="#{row}" id="ot3"/> </af:column>
</af:table>
结果看起来非常不错:
这种方法的唯一问题是该表不可更新。 它是只读的。
EL表达式“#{bindings.Arrvalue.inputValue.array}”将调用方法oracle.jbo.domain.Array.getArray() ,该方法返回一个不变的Object []数组,并且对该数组的所有修改都将丢失。
如果我们需要能够更新表中的数据,则必须执行以下操作:
- 制作bindings.Arrvalue.inputValue.array的副本
- 将此副本设置为表的值
- 在“更新模型值”阶段,将副本包装回oracle.jbo.domain.Array,并将其放入Arrvalue.inputValue。
因此,我们将制作一个副本并将其保留在请求范围托管的bean中:
private Object[] array = null;private Object[] createArray() {JUCtrlValueBinding dcb = getArrayCtrlBinding();if (dcb!=null){Array arr = (Array) dcb.getInputValue();if (arr!=null) {array = arr.getArray();} }return array;
}public void setArray(Object[] array) {this.array = array;
}public Object[] getArray() {return (array == null ? createArray() : array);
}private JUCtrlValueBinding getArrayCtrlBinding() {BindingContext bc = BindingContext.getCurrent();DCBindingContainer binding = (DCBindingContainer) bc.getCurrentBindingsEntry();return (JUCtrlValueBinding ) binding.findCtrlBinding("Arrvalue");
}
当使用此副本作为表的值时,我们可以执行以下操作:
<af:table value="#{TheBean.array}" var="row" id="t1"varStatus="status"><af:column sortable="false" headerText="Array Values" id="c1"><af:inputText value="#{TheBean.array[status.index]}" id="ot3"/> </af:column></af:table>
请注意,我们不仅使用#{row}作为inputText的值。 这将不起作用,因为#{row}只会返回一个不变的String。 取而代之的是,我们使用了varStatus表属性。 EL表达式#{TheBean.array [status.index]}使框架能够在“更新模型值”阶段调用相应的setter方法,因此表中所做的所有修改都将保存到TheBean.array中 。
最后一步是在“更新模型值”阶段将TheBean.array放回属性值。 为此,我们可以使用伪造的不可见的inputText :
<af:inputText value="#{TheBean.dummy}" visible="false" converter="EmptyConverter"id="it2"/>
此输入文本应放在页面上表格的下方。 这种方法的优点在于,框架将尝试在每个请求上更新inputText值。 因此,将表值保存到TheBean.array之后,将在更新模型值阶段对每个请求调用setter方法TheBean.setDummy(String dummy) 。 现在,我们将把数组包装到oracle.jbo.domain.Array中 ,然后放回Arrvalue.inputValue :
public void setDummy(String dummy) {getArrayCtrlBinding().setInputValue(new Array(array)); array = null;
}
此虚拟 inputText的秘密隐藏在EmptyConverter中:
public class EmptyConverter implements Converter {public Object getAsObject(FacesContext facesContext,UIComponent uIComponent, String string) {return null;}public String getAsString(FacesContext facesContext,UIComponent uIComponent, Object object) {return null;}
}
它模拟已随请求为此组件提交了空值。 另一方面, 伪获取器总是返回一个非空值:
public String getDummy() {return DUMMY;}
因此,该框架别无选择,只能在“更新模型值”阶段调用setDummy方法。
本文的示例应用程序需要JDeveloper 11.1.1.7。
而已!
翻译自: https://www.javacodegeeks.com/2014/04/working-with-the-array-data-type-in-a-table.html