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相关的主要类的核心代码。