OAF FlexField中数据库与页面的前后台数据类型转换(二)

2014-11-24 16:08:18 · 作者: · 浏览: 2
编辑):
[sql] 
SELECT   ExampleEO.example_id AS EXAMPLE_ID  
       , ExampleEO.information1 AS EFFECTIVE_DATE  
       , ExampleEO.information2 AS EMPLOYEE_NAME  
       , FND_DATE.CANONICAL_TO_DATE(ExampleEO.information1) AS DISP_EFFECTIVE_DATE     -- Invoking data type conversion procedure here  
FROM   ExampleEO  
WHERE  ExampleEO.example_id > 10    

其中,FND_DATE.CANONICAL_TO_DATE是Oracle自带的函数。这个函数把格式为'YYYY-MM-DD HH:MI:SS'的标准日期字符串(这种字符串也是Oracle FlexField使用字符串保存日期的标准格式),转换成Oracle数据库的Date类型。
而在OA Page上,显示的item中的View Attribute属性,只需要选择上述的DispEffectiveDate,则可以正常地显示出来了。有关日期的验证也可以如常使用。
小结:在VO的SQL中插入一个PL/SQL函数调用,把VARCHAR2类型的变量转换为DATE类型。在页面中则选择被转换后的VO属性。
4. 从页面保存到数据库(Page -> Table,从前台到后台)
把页面上的日期保存为标准日期字符串,方法也是类似的。唯一不同的地方是调用转换函数的地方。
在描述怎么转换之前,我们需要知道一点:在用户填写好表单,按提交按钮后,OAF首先会调用VORowImpl相应的setter方法,之后才会调用用户定义CO的ProcessFormRequest (PFR)函数。如果将数据类型转换函数放在AM或VOImpl中(这些转换函数使用setter来设置数据库中的值),在CO中用invokeMethod来调用它们,即使这些转换函数包含了异常的处理,假若用户如果再按多一次按钮,表单也会跳到成功的DialogPage(假设定义了DialogPage来提示成功)。
这个问题的原因是,OAF会在底层的某个地方调用ProcessFormData()函数。这个函数调用了一个名为setValue()的函数。在setValue()的函数中,首先会判定新值和旧值是否相等。如果相等,则会跳过所有的任务,直接返回。这样,写在VO或EO中的数据验证方法也不会被调用。这种新旧值相等的验证是写死在底层的代码中,开发者是无法设置的。
具体地说,假若业务上规定EffectiveDate的值不能在01-Jan-2000以前。当用户输入一个01-Jan-1999,第一次提交的时候,因为01-Jan-1999与null值不同,所以在setValue()会设置。而在设置的过程中,会进行验证,从而捕捉到异常。当用户马上按第二次提交,这时在VO中,DispEffectiveDate属性的值已是01-Jan-1999,和页面上的01-Jan-1999相同。所以setValue()不会再尝试设值,也不会做相应的验证,于是,非法的值就被保存了。
回到正题。刚才说到,OAF会先调用VORowImpl的setter方法。于是,数据类型转换可以写在VORowImpl方法中:
[java]
public void setDispEffectiveDate(Date value)
{
setEffectiveDate(dataTypeConversion(value));
setAttributeInternal(DISPEFFECTIVEDATE, value);
}
public void setEffectiveDate(String value)
{
setAttributeInternal(EFFECTIVEDATE, value);
}
其中,dataTypeConversion()是一个自己写的函数,它的定义如下:
[java]
private String dataTypeConversion(Date value)
{
// convert data type here
return ;
}
通过上面的方法,在设置DispEffectiveDate的值的同时,相对应的EffectiveDate属性的值也会被设置。当多种类型需要转换,还可以利用多态,复用dataTypeConversion()函数。
这里还有一个小细节需要注意。setEffectiveDate()的调用必须放在setAttributeInternal()之前。原因是,当setEffectiveDate()抛出异常,程序不会执行下面那一句setAttributeInternal()。就是说,在VO中,DispEffectiveDate这个属性的值依然是null,没被设置。那么,当用户再次提交,setValue()就会再次设值,并且调用VORowImpl的setter函数了。
小结:在VORowImpl中,添加数据类型转换函数。然后在transient属性的setter中,先于setAttributeInternal()调用前,调用数据库相应列属性的setter,利用数据类型转换函数转换类型并设值。
5. 总结
在一般情况下,OAF都会生成漂亮的属性名和函数名,函数异常也会处理得很好。但是当需要手工处理FlexField时,这些事情就需要手工做。
如果说OAF生成的代码所使用的方法是读写共用一个SQL语句,那么我们手工实现转换的时候,就需要将读和写的处理分离。
在VO的SQL中调用一个PL/SQL函数进行转换,并把这个转换的返回值显示到页面上,此乃读法;在VORowImpl中添加 Java转换函数,并在页面显示属性的setter中首先调用,此乃写法。
6. 补遗
a) 如果用户使用的不是EO based的VO,而是PL/SQL based,那么也可以在相应的PL/SQL package中,添加转换方法。
b) 关于程序异常处理,也是需要额外处理。在一般情况下,属性名在EO、VO中是统一的,而在FlexField中则不是如此。故此需要额外的处理。关于这个问题,会另外用文章说明。