nhibernate源碼分析之五: 對象標識

來源:互聯網
上載者:User
對象標識相當於資料表中的主鍵,在持久化中起著十分重要的作用,nhibernate通過對象標識來辨別兩個持久對象是否相等。

在對應檔中,通過id屬性來定義對象標識,內容如下:

  

其中unsaved-value屬性用來指明對象未持久化時的值,如果此值與未持久化的對象標識值不符,將無法save對象,generator用於指定標識對象的類型,常用的有identity, assigned等。

標識對象為實現IIdentitierGenerator介面的類,由IdentitierGeneratorFactory類根據對應檔的標識類型來建立,IIdentifierGenerator定義了Generate方法,用於產生對象標識。

1. 標識對象的建立

標識對象在持久化類AbstractEntityPersister中建立,通過它我們就可以對持久對象的標識進行操作了。

//*** AbstractEntityPersister.cs ***

public virtual IIdentifierGenerator IdentifierGenerator {
   get {
      if (idgen==null) {
         throw new HibernateException("...");
      }
      return idgen;
   }
}
idgen在建構函式中被賦值。

protected AbstractEntityPersister(PersistentClass model, ISessionFactoryImplementor factory) {
   // ...

   // GENERATOR
   idgen = model.Identifier.CreateIdentifierGenerator(dialect);
   useIdentityColumn = idgen is IdentityGenerator;
   identitySelectString = useIdentityColumn ? dialect.IdentitySelectString : null;

   // ...
}
其中model為PersistentClass或其子類,Identifier為Value類型的屬性。

// *** Value.cs ***

public IIdentifierGenerator CreateIdentifierGenerator(Dialect.Dialect dialect) {
   if ( uniqueIdentifierGenerator==null ) {
      uniqueIdentifierGenerator = IdentifierGeneratorFactory.Create(identifierGeneratorStrategy, type, identifierGeneratorProperties, dialect);
   }
   return uniqueIdentifierGenerator;
}

//*** IdentitifierGeneratorFactory ***

public static IIdentifierGenerator Create(string strategy, IType type, IDictionary parms, Dialect.Dialect dialect) {
   try {
      System.Type clazz = (System.Type) idgenerators[strategy];
      // ...
      if (clazz==null) clazz = System.Type.GetType(strategy);
      IIdentifierGenerator idgen = (IIdentifierGenerator) Activator.CreateInstance(clazz);
      if (idgen is IConfigurable) ((IConfigurable) idgen).Configure(type, parms, dialect);
      return idgen;
   }
   catch (Exception e)  {
      throw new MappingException("could not instantiate id generator", e);
   }
}

Create方法通過標識對象類名來建立標識對象。

2. 標識對象在持久化中的使用

在會話和持久化操作一文,我曾提到當前會話會把要持久化的Object Storage Service起來,直到調用Flush或關閉會話。儲存持久對象的集合為entitiesByKey,這是一個Hashtable,它的key為一個Key對象, value為持久對象,Key對象簡單的儲存持久對象的id和IdentifierSpace。

在進行持久化操作時,nhibernate必須首先檢查對象是否在entitiesByKey中,這由GetEntity方法完成,然後再根據對象是否在集合中作後續處理。

//*** SessionImpl.cs ***

public object GetEntity(Key key) {
   return entitiesByKey[key];
}

下面來看看DoUpdate中的處理:

private void DoUpdate(object obj, object id) {   
   // ...

   Key key = new Key(id, persister);
   object old = GetEntity(key);
   if (old==obj) {
      throw new AssertionFailure("Hibernate has a bug in Update() ... or you are using an illegal id type");
   }
   else if ( old!=null ) {
      throw new HibernateException("Another object was associated with this id ( the object with the given id was already loaded)");
   );

   // ...

   AddEntity(key, obj);
   AddEntry(obj, Status.Loaded, null, id, persister.GetVersion(obj), LockMode.None, true, persister);

   // ...
}
如果首次對持久對象執行Update,此時old為空白,操作順利執行,並且對象被加入到集合中,
當再次調用Update時(在同一會話中,並且沒有調用會導致Flush的操作),此時old不為空白,將引發一個異常。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.