如何动态创建table-OAF开发
发布网友
发布时间:2022-04-14 12:26
我来回答
共2个回答
懂视网
时间:2022-04-14 16:47
我们知道 MDS 是 MetaData Service 的缩写; 我们也知道 MDS 跟 OAF 框架中页面显示有某种关系. 让我们来理解一下 MDS 的基础知识. Meta: 在技术领域里面, meta 表示字典. 想象一下, 一个网页被分解成许多很小的单元( 单元格, 按钮, 选项框...). 这些小单元被
我们知道 "MDS" 是 "MetaData Service" 的缩写; 我们也知道 MDS 跟 OAF 框架中页面显示有某种关系. 让我们来理解一下 MDS 的基础知识.
Meta: 在技术领域里面, meta 表示"字典". 想象一下, 一个网页被分解成许多很小的单元( 单元格, 按钮, 选项框...). 这些小单元被存储在数据库中的一个字典( 表 )里面. 当把这些单元组合起来, 就变成一个在浏览器中显示的网页.
Data: 那些字典碎片( meta pieces) 并不是以二进制文件的方式存储的, 而是存储在数据库表中. 这些表的前缀是 "jdr", 比如 JDR_ATTRIBUTES, JDR_ATTRIBUTES_TRANS, JDR_COMPONENTS 和 JDR_PATHS. 所有的字段/区域/组件( field/region/component) 的定义和关系, 都存储在这些 JDR 的表中. 当你请求一个页面的时候, OAF 框架就会从数据库里面读取这些数据. 页面的结构就是从这些 MetaData 重构出来的.
Service: MetaData 可以作为一个服务使用. 所有的数据都存在 JDR 表中, 但是所有的这些数据都必须重新连接, 所有的字段, 区域, 按钮都必须以有意义的方式组成页面. 所以可以说, MDS 提供了一项服务, 来存储/重构网页页面. MDS 服务重新把零碎的页面组件组合成有意义的页面.
在 jDeveloper 中, 当我们在创建一个页面和区域, 看起来似乎是在创建一个 XML 文件. 在OAF 框架中, 页面定义是用 XML 文件来保存的吗?
实际上页面定义是存储在 JDR 表中的, 并不是以 XML 文件存储. 但是 MDS 提供了一个 API 接口, 用来把 JDR 表数据转化成 XML 描述性文件.
因此这里有两种形式:
1. 当我们设计页面的时候, 我们把页面的定义以 XML 格式保存在文件系统里面. 当我们部署服务器/系统的时候, 我们就需要把这些 XML 格式的文件导入到 JDR 表中. OAF 框架提供了导入工具 import:
例如用下面的的命令把 RcvBarCodeLovRN.xml 导入到数据库
C:Oraclep9879989jdevbinoaextinimport C:Oraclep17888411jdevhomejdevmyprojectsoracleappspo
cvlovwebuiRcvBarCodeLovRN.xml -rootdir C:Oraclep17888411jdevhomejdevmyprojects -username apps -password apps -dbconnection erik-lnx.oracle.com:1522:VID
select * from JDR_COMPONENTS where comp_id = 'SecTxnQtyColRN';
2. 当用户要显示一个页面的时候, OAF 框架做了下面的事情:
第一步. OAF 框架向 MDS 请求页面定义, 这会被缓存( 第一次打开页面会比较慢, 以后会比较快).
第二步. MDS 引擎向 OAF 框架返回一个 XML 文件
第三步. XML 文件中的每一个节点/组件( mode/component) 会被转化成一个 webBean 对象.
比方说有个页面, 结构如下:
Region-Main
field1
Region-Child
Button
在这个示例中, OAF 框架将会实例化4 个 webBean 对象, 每一个对象都代表了一个组件(field/button/region...). 每一个 webBean 对象都有一些方法比如: setRendered(), setRequired(), getRequired() 等等.
第四步. 这些 webBean 对象不仅被一个个创建出来, 而且他们之间是相互嵌套的, 嵌套的顺序跟页面定义时一样. 因此页面组件的父-子关系被保留下来.
第五步. 页面准备好之后, OAF 框架会调用 MDS 页面的控制器 controller( CO.class). 当 CO 中的processRequest() 方法执行完毕之后, 用户就可以看到页面了.
到现在为止, OAF 已经显示了 web page, 下面会发生什么呢?
在回答这个问题之前, 我们先回顾一下之前的步骤. 让我们回顾一下怎样定义这个页面的. 在OAF 中, 当我们定义一个页面的时候, 有两个关键步骤:
1. 为 page 定义一个 CO/controller
2. 定义一个 AM/application module 并附加到这个页面上.
当一个页面在浏览器中显示时, 会发生下面的事情:
a. 框架会在内存中, 根据 MDS 给出的 XML 文件建立一个 webBean 的层级关系, 用来表示页面的结构.
b. 创建一个 ApplicationModule 对象. 我们可以重新获取这个 AM 对象来管理页面的数据库状态.
c. CO 中的processRequest() 方法执行.
执行processRequest() 方法会传递哪些参数呢?
OAPageContext
OAWebBean
OAPageContext 参数有什么用处?
1. 使用 oaPageContext.getParameter() 和 oaPageContext.putParameter() 来设置获取和设置字段( field) 的值.
2. 重新导向页面到当前页面或者其他页面. 比如, oaPageContext.forwardImmediatelyToCurrentPage() 重新导向到当前页面, oaPageContext.sendRedirect(newPage) 导向到其他页面.
3. 获取 AM: oaPageContext.getRootApplicationModule(), 因为 AM 已经被附加到页面上了.
4. 写 debug 信息: oaPageContext.writeDiagnostics().
5. 从 FND 消息字典中获取信息: oaPageContext.getMessage().
OAWebBean 参数有什么用?
我们知道 webBean 对象表示了页面中的结构/层次关系. 因此用这个参数, 我们可以操作这个页面结构中的所有组件. 一旦我们获得了组件的对象( field bean or button bean), 我们就可以在 runtime 的时候用 setRendered() 等等方法来改变页面的行为.
例如:
1. OAWebBean lastName = oaWebBean.findIndexedChildRecursive("personLastName");
2. 获取一个区域的对象: OAStackLayoutBean oaStackLayoutBean = (OAStackLayoutBean) oaWebBean.findIndexedChildRecursive("stackRegionName");
3. 如上面两点所示, findIndexedChildRecursive() 方法返回的对象可以被映射到对应的 bean 对象.
问题集锦:
现在有一个页面, 里面的区域是嵌套的, 每一个区域都有自己的 CO/controller. 当页面出来的时候, 每一个 CO 中的 processRequest() 方法都会被执行吗?
回答: 会的. 内部区域的 CO 会先执行, 然后执行外部区域的 CO. 这很常见, 当你在主页面中添加一个公用区域( shared region) 的时候, 每一个公用区域都可能有自己的 CO.
MDS 页面定义会被缓存吗?
回答: 会的. 因此当在数据库中 update 了MDS, 就要重启 weblogic 服务器.
但是这对用 jDeveloper 测试页面不适用, jDeveloper 会先找本地的 XML 文件/本地MDS, 只有当本地文件系统找不到, 框架才会从数据库中去找页面定义.
热心网友
时间:2022-04-14 13:55
用以下的代码可以实现,但是有一点不足,就是当数据量比较多的时候,无法按照指定的行数进行分页显示。
先在页面上创建一个advancedTable,名字叫“region5”,即可。
public void processRequest(OAPageContext pageContext, OAWebBean webBean)
{
super.processRequest(pageContext, webBean);
final String CHILD_DATA_LIST = "childDataList";
final String TEXT = "text";
int COLUMN_COUNT = 0;
// write your Personalization SQL in here.
StringBuffer sbfSQL = new StringBuffer(200);
// set title in the advancedTable
sbfSQL.append("SELECT '名' user_name, 'ID' user_id, '开始日' FROM al \r\n");
sbfSQL.append("UNION ALL \r\n");
sbfSQL.append("SELECT fu.user_name, to_char(fu.user_id), to_char(fu.start_date) FROM fnd_user fu");
ResultSet rs = null;
Statement s = null;
Connection con = pageContext.getApplicationMole(webBean).getOADBTransaction().getJdbcConnection();
try
{
s = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = s.executeQuery(sbfSQL.toString());
ResultSetMetaData rsmd = rs.getMetaData();
COLUMN_COUNT = rsmd.getColumnCount();
rs.last();
int intRowCount = rs.getRow();
rs.first();
// find the advancedTable
OAAdvancedTableBean tableBean = (OAAdvancedTableBean)webBean.findChildRecursive("region5");
tableBean.setViewUsageName("");
for (int i = 1; i <= COLUMN_COUNT; i++)
{
// create a column
OAColumnBean cb = (OAColumnBean)createWebBean(pageContext, COLUMN_BEAN, null, null);
tableBean.addIndexedChild(cb);
// create MessageStyledText
OAMessageStyledTextBean mst = (OAMessageStyledTextBean)createWebBean(pageContext, MESSAGE_STYLED_TEXT_BEAN, null, null);
mst.setTextBinding(TEXT + i);
cb.addIndexedChild(mst);
// create title
OASortableHeaderBean shb = (OASortableHeaderBean)createWebBean(pageContext, SORTABLE_HEADER_BEAN, null, null);
shb.setPrompt(rs.getString(i));
cb.setColumnHeader(shb);
if (i != 1)
{
UINodeList colList = new DataObjectListNodeList(mst, new DataBoundValue(CHILD_DATA_LIST + i));
cb.setIndexedNodeList(colList);
}
}
// get row count;
DictionaryData rowData[] = new DictionaryData[intRowCount - 1];
int intRowLoop = 2;
// loop row
while (rs.next())
{
// setting 1 column cell value
rowData[intRowLoop - 2] = new DictionaryData(TEXT + "1", rs.getString(1));
// setting 2 to N column cell value
DictionaryData otherColumn[] = new DictionaryData[COLUMN_COUNT];
// loop column
for (int j = 2; j <= COLUMN_COUNT; j++)
{
otherColumn[j - 2] = new DictionaryData(TEXT + j, rs.getString(j));
rowData[intRowLoop - 2].put(CHILD_DATA_LIST + j , new ArrayDataSet(otherColumn));
}
intRowLoop++;
}
tableBean.setTableData(new ArrayDataSet(rowData));
}
catch (SQLException se)
{
se.printStackTrace();
}
finally
{
if (s != null)
{
try
{
s.close();
}
catch (SQLException se)
{
se.printStackTrace();
}
}
if (rs != null)
{
try
{
rs.close();
}
catch (SQLException se)
{
se.printStackTrace();
}
}
}
}