跳轉到內容

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 透過批次檢索主鍵而不是逐個檢索主鍵來進行一些最佳化。當使用以上程式碼時,您會失去這種最佳化。

華夏公益教科書