WebObjects/EOF/使用 EOF/主鍵
當你的主鍵不可見為類屬性時,獲得主鍵值的文件化方法是使用 EOUtilities.primaryKeyForObject()。這可行,但如果你有一個單一的非複合主鍵,你需要幾行程式碼來提取這個主鍵值。更麻煩的是,當 EOUtilities 方法在錯誤上呼叫時,會導致錯誤被解析。錯誤實際上並不需要解析來獲得主鍵,因為主鍵值即使在錯誤中也存在。
以下方法適用於具有單個 Integer 主鍵的 EO,用於提取該主鍵值,並且在對錯誤值呼叫時不會解析錯誤(可能導致訪問資料庫)。
public static Integer singleIntegerPrimaryKeyForObject(EOEnterpriseObject eo) {
EOEditingContext ec = eo.editingContext();
if (ec == null) {
//you don't have an EC! Bad EO. We can do nothing.
return null;
}
EOGlobalID gid = ec.globalIDForObject(eo);
if (gid.isTemporary()) {
//no pk yet assigned
return null;
}
EOKeyGlobalID kGid = (EOKeyGlobalID) gid;
NSArray keyValues = kGid.keyValuesArray();
if (keyValues.count() != 1 ||
! (keyValues.objectAtIndex(0) instanceof Integer))
return null;
return (Integer) keyValues.objectAtIndex(0);
}
你也可以使用 EOUtilities 方法,但請注意,至少在 WO5 中,此 EOUtilities 程式碼有兩個不太理想的方面。
- 如果 EO 是一個錯誤,呼叫 EOUtilities 方法會導致錯誤被解析,可能需要訪問資料庫,即使主鍵資訊已存在於錯誤中,訪問資料庫在此時實際上是不必要的。
- 如果 EO 剛剛被插入並且尚未提交,它還沒有主鍵,EOUtilities 程式碼將丟擲異常。這並不是一個與“還沒有主鍵”相對應的邏輯異常,而是一個由一些意外的 Apple 程式碼丟擲的未捕獲異常。
通常 EOF 不會在您實際在包含新建立的即將儲存的 EOEnterpriseObjects 的 EOEditingContext 上呼叫 saveChanges() 之前生成/插入主鍵。
但是,有時您希望在建立 EOEnterpriseObject 時立即分配一個永久主鍵,而不是等到它真正提交到資料庫。以下是一些程式碼來實現這一點,它會在給定情況下以與 EOF 稍後生成主鍵相同的方式生成主鍵,但會立即執行。[感謝 Pierre Barnard]
public void _insertObjectWithGlobalID(EOEnterpriseObject eo, EOGlobalID globalID)
{
EOEntity entity = EOUtilities.entityNamed(this, eo.entityName());
EODatabaseContext dbContext = EOUtilities.databaseContextForModelNamed(this, entity.model().name());
NSDictionary pkDict = primaryKeyDictionaryForDatabaseContextAndEntity(dbContext, entity);
if (pkDict == null || pkDict.count() != 1)
{
NSLog.err.appendln("Failed to generate primary key for entity " + entity.name() + ", or pk is compound.");
} else
{
Object pk = pkDict.allValues().lastObject();
globalID = EOKeyGlobalID.globalIDWithEntityName(entity.name(), new Object[] { pk });
}
super._insertObjectWithGlobalID(eo, globalID);
}
public static NSDictionary primaryKeyDictionaryForDatabaseContextAndEntity(EODatabaseContext dbContext, EOEntity entity) {
NSDictionary pk = null;
try {
dbContext.lock();
EOAdaptorChannel adaptorChannel = dbContext.availableChannel().adaptorChannel();
if (!adaptorChannel.isOpen()) {
adaptorChannel.openChannel();
}
pk = (NSDictionary) adaptorChannel.primaryKeysForNewRowsWithEntity(1, entity).lastObject();
}
catch (Exception e) {
NSLog.err.appendln("Can't get primary keys for entity " + entity.name() + " " + e);
}
finally {
dbContext.unlock();
return pk;
}
}
EOEditingContext 中有 2 個 insertObjectWithGlobalID 方法。其中一個方法名以下劃線開頭。常規方法似乎呼叫了該方法。對於大多數用途,覆蓋常規方法就足夠了。但是,對於 JavaClient,常規方法不會被呼叫。在伺服器端,只有帶下劃線的方法會被呼叫。您必須在伺服器端上下文中覆蓋帶下劃線的方法,因為以上程式碼僅在伺服器端有效。
如果您在標準 WO 應用程式中使用巢狀 EC,那麼如果您希望父 EC 處理主鍵建立,則可能需要覆蓋相同的部分私有方法。
順便說一句,我相信 EOF 透過批次檢索主鍵而不是逐個檢索主鍵來進行一些最佳化。當使用以上程式碼時,您會失去這種最佳化。