OAF VO初始化分析

目錄

第一部分 插入新行前的初始化

1 僅插入型VO的初始化

2 插入查詢VO的初始化

第二部分 執行查詢前的初始化

1 避免無條件查詢

2 避免多餘的查詢

 

正文

第一部分 插入新行前的初始化

在處理插入初始化之前,我們必須確定一件事情,就是當前我們要處理的這個VO,它是隻用作插入操作呢,還是即用作插入又用作查詢操作。比如一個EmployeeCreateVO,這個VO僅僅在創建新員工的頁面使用,不用做其他用途,那麼我們認爲它是一個只做插入操作的VO,反之,它就是一個即查詢又插入的VO.理清楚這一點,對合理初始化VO很重要。

1僅插入型的VO的初始化

我們可以利用如下代碼:

//檢查VO是否有行,如果有行了,我們就不用執行括號裏的語句了。vo.getFetchedRowCount()是檢查當前緩存中VO的行數,包括新插入的行,它不執行數據庫查詢,僅僅檢查內存中已經取出來的行。如VO已經被插入過行了,那麼getFetchedRowCount肯定大於0,就無需再調用setMaxFetchSize了

if (vo.getFetchedRowCount() == 0) {

//此方法是設置VO的每次查詢行數的上限,但是如果參數爲0的話,此方法會設置mPreparedForExecution標識爲TRUE。這個標識是OAViewObjectImpl的一個成員變量,表示VO是否準備好執行查詢,初始值是FALSE。當VO執行了executeQuery()之後,該標識值也會被設爲TRUE。

vo.setMaxFetchSize(0);

}

// 執行插入操作

Row row = vo.createRow();

vo.insertRow(row);

//遵循代碼標準M69,在所有新插入的行後立即將起設置爲STATUS_INITIALIZED狀態,讓此行處於脫管狀態,不參與事務提交,不參與驗證,直到在頁面上對這行數據進行更新,然後OA框架自動把狀態設回爲STATUS_NEW,以重新參與事務和驗證。

row.setNewRowState(Row.STATUS_INITIALIZED);

有時候我們會遇到這個錯誤:“違反了 OA 鈍化結構編碼標準。未正確準備全名爲EmployeeAM.EmployeeFullVO1 的視圖對象以供插入行。必須先調用視圖對象中的setMaxFetchSize(0) 或executeQuery()(或最終執行視圖對象查詢的任何等效方法),然後才能插入新行。”

我估計是OAF框架在遇到插入行的時候,會檢查當前VO有沒有行,如果沒有行,會檢查在這句代碼前面是否執行了executeQuery()或setMaxFetchedSize(0)語句(而不是檢查mPreparedForExecution的值是否爲TRUE),如果沒有執行這樣的語句,那麼就報告違反鈍化編碼標準。當然這只是我的個人猜測,僅供參考。

對於只包含瞬時屬性的VO,爲了避免OAF中的一些已知的BUG,我們在對其進行初始化的時候最好像下面這樣編寫代碼:

if (vo.getFetchedRowCount() == 0) {

vo.setMaxFetchSize(0);

vo.executeQuery();

... // Insert rows into the view object.

}

2帶數據庫查詢的VO的初始化

首先,我們必須注意,在這種既用於查詢又用於插入的VO情況下,我們必須先執行executeQuery(),然後再insertRow(),否則會導致一些鈍化上的問題。

提示1:

總的來說,儘量爲“創建**”或“插入**”型頁面單獨創建一個VO,比如單獨創建一個創建員工的VO,EmployeeCreateVO.

提示2:

如果實在需要插入和查詢或更新都公用一個VO,那麼在插入前,應該給executeQuery加上條件。

if (!vo.isExecuted()){

vo.executeQuery();

// 或者調用vo.initQuery(..),以便根據你自己WHERE條件進行查詢。

}

Row row=vo.createRow()

…其他初始化操作

注意:根據我個人經驗,由於mPreparedForExecution標識變量並不會在rollback()後變爲false,會造成未執行executeQuery()就進行insertRow()操作,那麼OA框架就會報告“違反了OA 鈍化結構編碼標準。未正確準備全名爲 EmployeeAM.EmployeeFullVO1的視圖對象以供插入行。必須先調用視圖對象中的 setMaxFetchSize(0) 或executeQuery()(或最終執行視圖對象查詢的任何等效方法),然後才能插入新行。”,所以在進行插入操作前,通過vo.isPreparedForExecution來作爲判斷條件不是最好的選擇,可以選擇用vo.isExecuted來代替。

第二部分 執行查詢前的初始化

1避免無條件查詢

一般情況下,我們可以使用下面的方法來避免無條件執行查詢操作

if (!vo.isPreparedForExecution()) {//帶條件執行查詢操作

vo.executeQuery();

// 或者調用vo.initQuery(..),以便根據你自己WHERE條件進行查詢。

}

無條件執行查詢操作會導致一些事務狀態的丟失,比如,對瞬時屬性(transient view objectattributes)數據的更新會丟失,VO的current Row和currentRange會被重設。這也就從一定解釋了“翻頁後在有刪除確認對話框的頁面中無法刪除行的案例”,具體參考我的另一篇文章《翻頁後在有刪除確認對話框的頁面中無法刪除行的案例》。

但是,有幾種情況你不應該給查詢加上條件:

1.你的頁面是隻讀的,你不在乎VO的事務狀態,你只希望每次渲染頁面的時候都能看到數據庫中的最新數據。

2.如果這個查詢是在processFormRequest中調用的,例如,頁面上有一個“GO”按鈕,希望點擊的時候查詢出滿足我需要的數據,那麼這個時候也不要給他加上面的條件。因此,我們可以這樣理解,上面的“帶條件執行查詢操作”僅用於在processRequest中對頁面包含的VO的數據進行初始化操作。

3.加了這個條件後,在保持同一個AM的範圍內,這個vo只被查詢一次,以後不會再被查詢,如果想重新執行查詢,得到最新的數據,那麼需要釋放AM。

對於下鑽頁面(Drilldown TargetPage),比如搜索結果頁面中點擊員工姓名下鑽到員工的詳細信息,我們也不能依賴於isPreparedForExecution的判斷,它太容易返回true了,以至於我們的查詢得不到執行,我們更喜歡用vo.findByKey()這個方法,這個方法是根據VO下面的EO主鍵來查詢,首先會檢查緩存中有沒有這條數據,沒有才去執行數據庫查詢。注意,下鑽頁面的VO和搜索頁面的VO最好不要使用同一個,以免下鑽後,影響搜索頁面的狀態。

public void initDetails(Number employeeNumber){

EmployeeFullVOImpl vo = getEmployeeFullVO1();

Number[] keys = { employeeNumber};

Row[] rows = vo.findByKey(new Key(keys), 1);

// findByKey不會改變currentRow指針,所以需要我們手動去更改,否則頁面上不會顯示值。

if ((rows != null) &&(rows.length > 0)) {

vo.setCurrentRow(rows[0]);

} } // end initDetails()

2避免多餘查詢

涉及個性化,暫不討論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章