Hibernate的原始碼編譯為eclipse專案後,下一步就開始原始碼的學習了,但應該從哪一塊的原始碼看起,也沒有一個確定的方案,暫時準備結合Hibernate的教程中的章節進行原始碼的閱讀。
初步方案是根據Hibernate的手冊,按照介紹的章節檢視對應的原始碼,分析核心部分的原始碼,並結合Hibernate開發嚮導中的內容,深入理解背後的原理,第一步從hibernate的配置檔案的載入和解析相關的程式碼讀起。
在原始碼學習之前,首先介紹一下Hibernate中自帶的文件,應該說這是學習Hibernate最權威也最全面的資料了,下載Hbiernate後解壓,在根目錄的documentation資料夾中,可以看到四個子目錄,分別包含Hibernate的四份文件。除了Hibernate的Javadoc之外,其他三份都是幫助理解和使用Hibernate的,只是各有側重。
(1)quickstart的篇幅最少,主要介紹Hibernate的核心部分的使用教程,以及一些示例。
(2)manual的內容最多,也最全面的,包含了Hibernate的原理和使用的方方面面。
(3)devguide是開發者嚮導手冊,側重於介紹實際開發中所涉及到的方面,以開發中使用Hibernate的不同方面為主題,介紹了資料庫訪問、事務控制、持久化上下文、鎖、快取、服務等內容。
美中不足的是,最新版本中自帶的文件全部是英文的。當前Hibernate官方網站上,中文版的文件更新到了Hibernate3.6,但是也只有核心手冊有,其他的還都只有英文版,具體的下載地址為http://hibernate.org/docs,可根據自己所需要的版本下載對應的文件。
因為下載的是最新的程式碼,因此,結合的也是最新的文件,最新版本的Hibernate是8月28號剛剛釋出的Hibernate4.2.5最終版。
下載地址:
http://downloads.sourceforge.net/project/hibernate/hibernate4/4.2.5.Final/hibernate-release-4.2.5.Final.zip
好,言歸正傳,現在開始原始碼學習,本節主要學習一下Hibernate對映檔案相關的知識。
Hibernate之所以能夠知道如何載入和儲存一個持久化類的物件,是因為Hibernate的對映檔案在其作用;即.hbm檔案。對映檔案會告訴Hibernate它將要訪問的是資料庫的那個表,會用到哪些表欄位。
Hibernate對映檔案有一份對應的DTD檔案用於規範.hbm的元素及其內容,具體的DTD的地址為:http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd
下載該檔案後開啟,發現其一共有1069行之多,其中詳細規定了對映檔案中的每個元素,及其元素所包含的值的型別,範圍等,關於DTD的相關知識可以參考:
中文:http://www.w3school.com.cn/dtd/
英文:http://en.wikipedia.org/wiki/Document_Type_Definition
參照hbm檔案的DTD來看一下hbm檔案的組成結構:
參看DTD可知,hbm檔案的根節點為hibernate-mapping,其結構應該包含的子節點如下:
meta*,
identifier-generator*,
typedef*,
filter-def*,
import*,
(class|subclass|joined-subclass|union-subclass)*,
resultset*,
(query|sql-query)*,
filter-def*,
fetch-profile*,
database-object*
)>
主要包含後設資料,id生成器、型別定義等。
meta元素被用來分配後設資料級別的屬性給一個類或屬性,當前被程式碼生成器用作那些與物件對映沒有直接關聯的值的佔位符。
identifier-generator元素允許自定義的id生成器實現的短命名。包含name和class兩個必須的子元素,預設為空。
class元素規定了該hbm檔案所對應的對映類,其組成元素如下:
<!ELEMENT class (
meta*,
subselect?,
cache?,
synchronize*,
comment?,
tuplizer*,
(id|composite-id),
discriminator?,
natural-id?,
(version|timestamp)?,
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
((join*,subclass*)|joined-subclass*|union-subclass*),
loader?,sql-insert?,sql-update?,sql-delete?,
filter*,
fetch-profile*,
resultset*,
(query|sql-query)*
)>
包含的屬性列表,僅列出了常用的幾個屬性
<!ATTLIST class entity-name CDATA #IMPLIED>
<!ATTLIST class name CDATA #IMPLIED> <!-- this is the class name -->
<!ATTLIST class table CDATA #IMPLIED> <!-- default: unqualified classname -->
<!ATTLIST class schema CDATA #IMPLIED> <!-- default: none -->
<!ATTLIST class catalog CDATA #IMPLIED> <!-- default: none -->
<!ATTLIST class dynamic-update (true|false) "false">
<!ATTLIST class dynamic-insert (true|false) "false">
<!ATTLIST class batch-size CDATA #IMPLIED>
其中比較重要的屬性有name和table,name是對應的類名,table是對應的資料表名稱。
另一個比較常見的子節點應該是property,其結構如下,此處也僅保留幾個常用的屬性
<!ELEMENT property (meta*,(column|formula)*,type?)>
<!ATTLIST property name CDATA #REQUIRED>
<!ATTLIST property type CDATA #IMPLIED>
<!ATTLIST property column CDATA #IMPLIED>
<!ATTLIST property length CDATA #IMPLIED>
<!ATTLIST property precision CDATA #IMPLIED>
<!ATTLIST property scale CDATA #IMPLIED>
<!ATTLIST property not-null (true|false) #IMPLIED>
此外,規定主鍵的的主要屬性如下,參加id的註釋可知,這個節點用於定義主鍵的型別、對應的資料列名稱已經其值的生成演算法,如果為這個id定義了一個name屬性,這個id通過class對應name的屬性暴露給應用程式,否則,這個id僅能通過Session.getIdentifier()來暴露給應用程式
<!ELEMENT id (meta*,column*,type?,generator?)>
<!ATTLIST id name CDATA #IMPLIED>
<!ATTLIST id column CDATA #IMPLIED>
<!ATTLIST id type CDATA #IMPLIED>
<!ATTLIST id length CDATA #IMPLIED>
Hibernate對映檔案相關程式碼的包為org.hibernate.mapping。該包中包含11個介面和48個類和一個列舉定義。包含了所有資料庫表關係對映所需的物件,如主鍵、外來鍵、表連線、索引、一對一、多對一,以及一些資料庫輔助功能的對映,例如觸發器和儲存過程。唯一的列舉MetadataSource用於規定對映的資料來源,包含三個值:HBM、ANNOTATIONS、OTHER,即hbm檔案、註解和其他。而對於主鍵的id生成,相關的程式碼則在org.hibernate.id包中,下一篇筆記將深入看一下這兩個包中與hbm相關的主要類的核心程式碼。