在这篇文章中,我想跟进我以前关于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