在 Fusion Web 应用程序中单击按钮后重新加载 ADF table
Reload ADF table after button click in a Fusion Web application
我最近开始使用 JDeveloper 12c 处理我的第一个 ADF 项目。
所以,我有一个连接到 Oracle 数据库的融合 Web 应用程序。在其中一个 jsf 页面上有两个 ADF 表,它们显示来自数据库的数据。下面是一个按钮,它向数据库发送“DELETE”语句以删除选定的条目。由于 两个 表必须在此之后刷新(删除会影响两个表的显示条目)。
在我对表格显示正确数据和按钮也发挥作用感到非常高兴之后,我很快意识到如果数据库发生变化,jsf 页面中的表格将不会自动刷新。我在网上搜索了一些关于如何在 ADF Fusion 应用程序中刷新 jsf 页面元素的入门教程。遗憾的是,到目前为止我还没有找到任何能给我打开它的钥匙的东西。
我在Oracle HQ页面上找到了this article,但是它也有使用很多专有命名的习惯,而且是用流畅的文字写的,所以里面没有代码示例或片段之类的,这让菜鸟很难跟上。
这是我的托管 java bean 的一个片段,我在其中存储我的按钮功能:
public String update() {
getDBConnection c = new DBConnection();
Connection conn = c.getConn();
RowKeySet selectedEntries = getDetailTable().getSelectedRowKeys();
Iterator selectedEntryIter = selectedEntries.iterator();
DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding entryIter = bindings.findIteratorBinding("my_iterator");
RowSetIterator rSIter = entryIter.getRowSetIterator();
try {
PreparedStatement pstmt1 = conn.prepareStatement("DELETE ...");
PreparedStatement pstmt2 = conn.prepareStatement("DELETE ...");
while(selectedEntryIter.hasNext()){
Key key = (Key)((List)selectedEntryIter.next()).get(0);
Row currentRow = rSIter.getRow(key);
BigDecimal barcode = (BigDecimal) currentRow.getAttribute("id");
BigDecimal field1 = (BigDecimal) currentRow.getAttribute("field1");
BigDecimal field2 = (BigDecimal) currentRow.getAttribute("field2");
pstmt1.setBigDecimal(1, id);
pstmt1.setBigDecimal(2, field1);
pstmt2.setBigDecimal(1, id);
pstmt2.setBigDecimal(2, field2);
pstmt1.executeUpdate();
pstmt2.executeUpdate();
}
conn.commit();
//i guess here i have to trigger to refresh the tables but I have pretty to no clue of how to do that
//where do I have to set the functionality? I read sth about creating another bean in the "session" package
//but somehow i have to access the jsf i want to have refreshed. Where do I create that connection?
//even a simple example or a good reference to a tutorial would be helpful for me
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return null;
}
可能这个问题与一个已经存在的问题重复,我太笨了,找不到它,但我还是会试一试。提前致谢!
在你的情况下,你可以简单地添加一个 entryIter.executeQuery();在 conn.commit() 之后; (您还应避免 运行 直接 sql 删除并使用标准 ADF BC DELETE https://o7planning.org/11489/create-update-and-delele-data-using-adf-form-in-adf-bc#a9769791)
但为了回答未来查询的问题标题,下面是一个简单的刷新 table 按钮的示例,易于重复使用,我通常将其添加到我的客户 table 的工具栏上:
//in your jsff
<af:panelCollection id="pc" >
<f:facet name="menus"/>
<f:facet name="statusbar"/>
<f:facet name="toolbar">
<af:toolbar id="t1" flex="5">
<af:group id="g1">
<af:commandImageLink shortDesc="Reload" partialSubmit="true" actionListener="#{YOUR_SCOPE.YOUR_BEAN.refreshTable}"
icon="#{resource['images:YOUR_RELOAD_ICON.png']}">
<f:attribute name="tableIdToRefresh" value="YOUR_TABLE_ID"/>
</af:commandImageLink>
</af:group>
</af:toolbar>
</f:facet>
<af:table id="YOUR_TABLE_ID" value="#{bindings.YOUR_VO.collectionModel}" var="row" rows="#{bindings.YOUR_VO.rangeSize}"
selectedRowKeys="#{bindings.YOUR_VO.collectionModel.selectedRow}" selectionListener="#{bindings.YOUR_VO.collectionModel.makeCurrent}" rowSelection="single"
fetchSize="#{bindings.YOUR_VO.rangeSize}" filterModel="#{bindings.XxcnVieIntSearchVCQuery.queryDescriptor}"
queryListener="#{bindings.XxcnVieIntSearchVCQuery.processQuery}" varStatus="vs" >
<!-- COLUMNS -->
</af:table>
</af:panelCollection>
//in your bean #{YOUR_SCOPE.YOUR_BEAN.refreshTable}
public void refreshTable(ActionEvent actionEvent) {
//Get the attribute tableIdToRefresh value. I like to have it as a jsff attribute so i can easily reuse the button elsewhere
String tableToRefreshId = "" + ((RichCommandImageLink)actionEvent.getSource()).getAttributes().get("tableIdToRefresh");
if (sValeurCode != null) {
addPprToComponentById(tableToRefreshId);
//If it doesn't suffice (see below) you can use this :
//refreshTableIterator(tableToRefreshId);
}
}
public static void addPprToComponentById(String id) {
Object component = findComponentInRoot(id); //from the great JSFUtils library
if (component != null) {
AdfFacesContext.getCurrentInstance().addPartialTarget((UIComponent)component);
AdfFacesContext.getCurrentInstance().partialUpdateNotify((UIComponent)component);
}
}
/**
* Locate an UIComponent in view root with its component id. Use a recursive way to achieve this.
* @param id UIComponent id
* @return UIComponent object
*/
public static UIComponent findComponentInRoot(String id) {
UIComponent component = null;
if (id != null) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null) {
UIComponent root = facesContext.getViewRoot();
if (root != null) {
component = findComponent(root, id);
}
}
}
return component;
}
您也可以将此 addPPR 逻辑用于其他组件。
如果简单的 ppr 还不够。您可以强制执行 table 查询:
public static void refreshTableIterator(String tableId) {
RichTable table = findComponentInRoot(tableId);
DCIteratorBinding treeIterator = null;
if (table != null) {
treeIterator = getTableIterator(table);
if (treeIterator != null) {
RowSetIterator rsi = treeIterator.getRowSetIterator();
treeIterator.executeQuery();
rsi.closeRowSetIterator();
}
}
}
public static DCIteratorBinding getTableIterator(RichTable table) {
DCIteratorBinding treeIterator = null;
CollectionModel model = (CollectionModel)table.getValue();
if (model != null) {
JUCtrlHierBinding treeBinding = (JUCtrlHierBinding)model.getWrappedData();
if (treeBinding != null) {
treeIterator = treeBinding.getDCIteratorBinding();
}
}
return treeIterator;
}
我最近开始使用 JDeveloper 12c 处理我的第一个 ADF 项目。
所以,我有一个连接到 Oracle 数据库的融合 Web 应用程序。在其中一个 jsf 页面上有两个 ADF 表,它们显示来自数据库的数据。下面是一个按钮,它向数据库发送“DELETE”语句以删除选定的条目。由于 两个 表必须在此之后刷新(删除会影响两个表的显示条目)。
在我对表格显示正确数据和按钮也发挥作用感到非常高兴之后,我很快意识到如果数据库发生变化,jsf 页面中的表格将不会自动刷新。我在网上搜索了一些关于如何在 ADF Fusion 应用程序中刷新 jsf 页面元素的入门教程。遗憾的是,到目前为止我还没有找到任何能给我打开它的钥匙的东西。
我在Oracle HQ页面上找到了this article,但是它也有使用很多专有命名的习惯,而且是用流畅的文字写的,所以里面没有代码示例或片段之类的,这让菜鸟很难跟上。
这是我的托管 java bean 的一个片段,我在其中存储我的按钮功能:
public String update() {
getDBConnection c = new DBConnection();
Connection conn = c.getConn();
RowKeySet selectedEntries = getDetailTable().getSelectedRowKeys();
Iterator selectedEntryIter = selectedEntries.iterator();
DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding entryIter = bindings.findIteratorBinding("my_iterator");
RowSetIterator rSIter = entryIter.getRowSetIterator();
try {
PreparedStatement pstmt1 = conn.prepareStatement("DELETE ...");
PreparedStatement pstmt2 = conn.prepareStatement("DELETE ...");
while(selectedEntryIter.hasNext()){
Key key = (Key)((List)selectedEntryIter.next()).get(0);
Row currentRow = rSIter.getRow(key);
BigDecimal barcode = (BigDecimal) currentRow.getAttribute("id");
BigDecimal field1 = (BigDecimal) currentRow.getAttribute("field1");
BigDecimal field2 = (BigDecimal) currentRow.getAttribute("field2");
pstmt1.setBigDecimal(1, id);
pstmt1.setBigDecimal(2, field1);
pstmt2.setBigDecimal(1, id);
pstmt2.setBigDecimal(2, field2);
pstmt1.executeUpdate();
pstmt2.executeUpdate();
}
conn.commit();
//i guess here i have to trigger to refresh the tables but I have pretty to no clue of how to do that
//where do I have to set the functionality? I read sth about creating another bean in the "session" package
//but somehow i have to access the jsf i want to have refreshed. Where do I create that connection?
//even a simple example or a good reference to a tutorial would be helpful for me
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return null;
}
可能这个问题与一个已经存在的问题重复,我太笨了,找不到它,但我还是会试一试。提前致谢!
在你的情况下,你可以简单地添加一个 entryIter.executeQuery();在 conn.commit() 之后; (您还应避免 运行 直接 sql 删除并使用标准 ADF BC DELETE https://o7planning.org/11489/create-update-and-delele-data-using-adf-form-in-adf-bc#a9769791)
但为了回答未来查询的问题标题,下面是一个简单的刷新 table 按钮的示例,易于重复使用,我通常将其添加到我的客户 table 的工具栏上:
//in your jsff
<af:panelCollection id="pc" >
<f:facet name="menus"/>
<f:facet name="statusbar"/>
<f:facet name="toolbar">
<af:toolbar id="t1" flex="5">
<af:group id="g1">
<af:commandImageLink shortDesc="Reload" partialSubmit="true" actionListener="#{YOUR_SCOPE.YOUR_BEAN.refreshTable}"
icon="#{resource['images:YOUR_RELOAD_ICON.png']}">
<f:attribute name="tableIdToRefresh" value="YOUR_TABLE_ID"/>
</af:commandImageLink>
</af:group>
</af:toolbar>
</f:facet>
<af:table id="YOUR_TABLE_ID" value="#{bindings.YOUR_VO.collectionModel}" var="row" rows="#{bindings.YOUR_VO.rangeSize}"
selectedRowKeys="#{bindings.YOUR_VO.collectionModel.selectedRow}" selectionListener="#{bindings.YOUR_VO.collectionModel.makeCurrent}" rowSelection="single"
fetchSize="#{bindings.YOUR_VO.rangeSize}" filterModel="#{bindings.XxcnVieIntSearchVCQuery.queryDescriptor}"
queryListener="#{bindings.XxcnVieIntSearchVCQuery.processQuery}" varStatus="vs" >
<!-- COLUMNS -->
</af:table>
</af:panelCollection>
//in your bean #{YOUR_SCOPE.YOUR_BEAN.refreshTable}
public void refreshTable(ActionEvent actionEvent) {
//Get the attribute tableIdToRefresh value. I like to have it as a jsff attribute so i can easily reuse the button elsewhere
String tableToRefreshId = "" + ((RichCommandImageLink)actionEvent.getSource()).getAttributes().get("tableIdToRefresh");
if (sValeurCode != null) {
addPprToComponentById(tableToRefreshId);
//If it doesn't suffice (see below) you can use this :
//refreshTableIterator(tableToRefreshId);
}
}
public static void addPprToComponentById(String id) {
Object component = findComponentInRoot(id); //from the great JSFUtils library
if (component != null) {
AdfFacesContext.getCurrentInstance().addPartialTarget((UIComponent)component);
AdfFacesContext.getCurrentInstance().partialUpdateNotify((UIComponent)component);
}
}
/**
* Locate an UIComponent in view root with its component id. Use a recursive way to achieve this.
* @param id UIComponent id
* @return UIComponent object
*/
public static UIComponent findComponentInRoot(String id) {
UIComponent component = null;
if (id != null) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null) {
UIComponent root = facesContext.getViewRoot();
if (root != null) {
component = findComponent(root, id);
}
}
}
return component;
}
您也可以将此 addPPR 逻辑用于其他组件。
如果简单的 ppr 还不够。您可以强制执行 table 查询:
public static void refreshTableIterator(String tableId) {
RichTable table = findComponentInRoot(tableId);
DCIteratorBinding treeIterator = null;
if (table != null) {
treeIterator = getTableIterator(table);
if (treeIterator != null) {
RowSetIterator rsi = treeIterator.getRowSetIterator();
treeIterator.executeQuery();
rsi.closeRowSetIterator();
}
}
}
public static DCIteratorBinding getTableIterator(RichTable table) {
DCIteratorBinding treeIterator = null;
CollectionModel model = (CollectionModel)table.getValue();
if (model != null) {
JUCtrlHierBinding treeBinding = (JUCtrlHierBinding)model.getWrappedData();
if (treeBinding != null) {
treeIterator = treeBinding.getDCIteratorBinding();
}
}
return treeIterator;
}