跳轉到內容

WebObjects/EOF/使用 EOF/問題

來自華夏公益教科書,開放的書籍,為開放的世界

本節描述使用企業物件框架時有時會遇到的一些問題和錯誤。

EOF 在未明確排序時無法初始化模型

[編輯 | 編輯原始碼]
作者:Francis Labrie
受影響的產品:WebObjects 5.2.x, 5.3.x
錯誤參考:rdar://4571773

有時,在WebObjects應用程式中使用多個使用共享物件的資料庫模型時,模型載入、初始化和連線會簡單地失敗,並出現奇怪且意外的異常。常見的異常是

  • java.lang.IllegalStateException: registeredDatabaseContextForModel() 無法為模型註冊資料庫上下文 <模型名稱>
at com.webobjects.eoaccess.EODatabaseContext.registeredDatabaseContextForModel(EODatabaseContext.java:1145)
...
  • java.lang.IllegalStateException: addOrderByAttributeOrdering: 嘗試為 com.webobjects.eocontrol.EOSortOrdering <class com.webobjects.eocontrol.EOSortOrdering(<屬性名稱> compareAscending)> 生成 SQL 失敗,因為透過鍵 '<屬性名稱>' 標識的屬性無法從實體 '<實體名稱>' 訪問。
at com.webobjects.eoaccess.EOSQLExpression.addOrderByAttributeOrdering(EOSQLExpression.java:1803)
...
  • 等等。

我在多個郵件列表中看到了有關此錯誤的報告,但沒有一個報告能找到正確的解決方案或合理的解釋。

http://lists.apple.com/archives/webobjects-dev/2005/Aug/msg00295.html
http://www.wodeveloper.com/omniLists/webobjects-dev/2004/September/msg00255.html

解決方案

[編輯 | 編輯原始碼]

我最終發現這個問題與模型載入和初始化順序有關。大多數情況下,EOF 都能完美地初始化一組模型。但在某些情況下,它就會失敗。

最好的解決方案是讓 EOF 動態分析模型組,為每個組構建一個包含所有實體的依賴關係圖,並根據此圖對模型和實體的初始化進行排序。但這種解決方案稍微複雜一些,通常應該直接整合到 EOAccess 層中。

為了使用更簡單的解決方案來解決此錯誤,可以在每個模型的userInfo字典中新增priority鍵,並將其分配給一個四位數的值,例如:010005002000等。必須使用具有相同位數的優先順序值,因為這些值將被轉換為字串,如果您設定的優先順序為500,則字串值將被視為高於優先順序為1000的值。

然後,建立一個靜態方法,使用按優先順序排序的組中的每個模型執行assertConnectionDictionaryIsValid()操作。

	private static final NSArray _PriorityDescendingModelSortOrdering = new NSArray(new Object[] {
		EOSortOrdering.sortOrderingWithKey("userInfo.priority", EOSortOrdering.CompareDescending), 
		EOSortOrdering.sortOrderingWithKey("name", EOSortOrdering.CompareAscending)
	});

...

	public static void assertModelGroupConnectionDictionariesAreValid(EOEditingContext editingContext, EOModelGroup modelGroup) {
		Enumeration models;
		EOAdaptor adaptor;
		EODatabaseContext databaseContext;
		EOModel model;

		// Get models enumerator from default group
		models = EOSortOrdering.sortedArrayUsingKeyOrderArray(modelGroup.models(), 
			_PriorityDescendingModelSortOrdering).objectEnumerator();

		while(models.hasMoreElements()) {
			model = (EOModel)models.nextElement();
			NSLog.debug.appendln("  Connecting " + model.name() + " model, userInfo = " + model.userInfo() + "...");
			databaseContext = EODatabaseContext.registeredDatabaseContextForModel(model, editingContext);
			adaptor = databaseContext.adaptorContext().adaptor();

			// Test connection dictionary
			adaptor.assertConnectionDictionaryIsValid();
			NSLog.debug.appendln("  The \"" + model.name() + "\" model is connected.");
		} // while
	} // assertConnectionDictionariesAreValid

此處的排序順序是按模型優先順序降序和模型名稱升序排序,以確保排序結果的一致性。

您將不得不找到正確的模型順序:您可以透過邏輯繪製依賴關係圖來推斷它,也可以透過測試和錯誤來找到它。通常,當丟擲上述異常時,這是因為模型初始化完成得太晚。我通常將框架模型的優先順序設定為從1000(低)到9000(高),將應用程式模型的優先順序設定為從0100(低)到0900(高)。

對於某些情況,此解決方案仍然無濟於事(請參閱此郵件)。我懷疑模型中的實體排序是問題所在(請參閱下面的#EOF 在模型中未正確排序時無法獲取或儲存實體)。如果仍然不是這種情況,您可以嘗試在Project Wonder中使用ERXSharedEOLoader 類。

EOF 在模型中未正確排序時無法獲取或儲存實體

[編輯 | 編輯原始碼]
作者:Francis Labrie
受影響的產品:WebObjects 5.2.x, 5.3.x
錯誤參考

有時,在WebObjects應用程式中,在資料庫模型中使用實體繼承時,獲取或儲存資料可能會簡單地失敗,並出現奇怪且意外的異常。常見的異常是

  • com.webobjects.eoaccess.EOGeneralAdaptorException: sqlStringForKeyValueQualifier: 嘗試為 <限定符類> (<限定符表示式>) 生成 SQL 失敗,因為透過鍵 'NeededByEOF0' 標識的屬性無法從實體 <實體名稱> 訪問。
at com.webobjects.eoaccess.EODatabaseContext._exceptionWithDatabaseContextInformationAdded(EODatabaseContext.java:4685)
...
  • 等等。

解決方案

[編輯 | 編輯原始碼]

通常,這種錯誤發生在父實體位於另一個模型中,而該模型是在當前實體模型初始化之後初始化的(請參閱上面的#EOF 在未明確排序時無法初始化模型),或者父實體在當前模型中按字母順序排列的實體列表中位於當前實體之後。為了說明後一種情況:如果您的抽象父實體名稱為“Flower”,並且您正在獲取具體子實體“Anemone”,而這兩個實體都是同一個模型的一部分,那麼您可能會在第一次獲取“Anemone”時遇到這種異常。

為了避免此異常,只需在文字編輯器中編輯“index.eomodeld”檔案並重新排序陣列中的實體引用,將父實體置於子實體之上。但您隨後需要小心使用EOModeler:每次修改和儲存模型時,都需要重新排序這些實體引用。

新的子實體插入失敗,因為主鍵為空

[編輯 | 編輯原始碼]
作者:最初由 Chuck Hill 報告
受影響的產品:WebObjects 5.2.x, 5.3.x
錯誤參考

當子實體的父實體具有設定為傳播主鍵的關係時,在從編輯上下文儲存更改時插入任何新的子實體都會引發完整性違規異常,因為主鍵列設定為null

解決方案

[編輯 | 編輯原始碼]

為了避免此錯誤,取消選中父實體的傳播主鍵關係屬性。不幸的是,如果父實體不是抽象的,則此解決方案將不適用:您可能需要修改關係建模本身。

華夏公益教科書