Hibernate需要知道怎样去加载(load)和存储(store)我们的持久化类的对象。这里正是Hibernate映射文件(mapping file)发挥作用的地方。 映射文件告诉Hibernate它应该访问数据库里面的哪个表(table)和应该使用表里面的哪些字段(column)。
一个映射文件的基本结构看起来像这样:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> [...] </hibernate-mapping>
注意Hibernate的DTD是非常复杂的。 你可以在你的编辑器或者IDE里面使用它来自动提示并完成(auto-completion)那些用来映射的XML元素(element)和属性(attribute)。 你也可以用你的文本编辑器打开DTD-这是最简单的方式来浏览所有元素和参数,查看它们的缺省值以及它们的注释,以得到一个整体的概观。 同时也要注意Hibernate不会从web上面获取DTD文件,虽然XML里面的URL也许会建议它这样做,但是Hibernate会首先查看你的程序的classpath。 DTD文件被包括在hibernate3.jar,同时也在Hibernate分发版的src/路径下。
在以后的例子里面,我们将通过省略DTD的声明来缩短代码长度。但是显然,在实际的程序中,DTD声明是必须的。
在两个hibernate-mapping标签(tag)中间, 我们包含了一个 class元素(element)。所有的持久性实体类(persistent entity classes)(再次声明, 这里也包括那些依赖类,就是那些次要的实体)都需要一个这样的映射,来映射到我们的SQL database。
<hibernate-mapping> <class name="Event" table="EVENTS"> </class> </hibernate-mapping>
我们到现在为止做的一切是告诉Hibernate怎样从数据库表(table)EVENTS里持久化和 加载Event类的对象,每个实例对应数据库里面的一行。现在我们将继续讨论有关唯一标识属性(unique identifier property)的映射。 另外,我们不希望去考虑怎样产生这个标识属性,我们将配置Hibernate的标识符生成策略(identifier generation strategy)来产生代用主键。
<hibernate-mapping> <class name="Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="increment"/> </id> </class> </hibernate-mapping>
id元素是标识属性(identifer property)的声明, name="id" 声明了Java属性(property)的名字 - Hibernate将使用getId()和setId()来访问它。 字段参数(column attribute)则告诉Hibernate我们使用EVENTS表的哪个字段作为主键。 嵌套的generator元素指定了标识符的生成策略 - 在这里我们使用increment,这个是非常简单的在内存中直接生成数字的方法,多数用于测试(或教程)中。 Hibernate同时也支持使用数据库生成(database generated),全局唯一性(globally unique)和应用程序指定(application assigned) (或者你自己为任何已有策略所写的扩展) 这些方式来生成标识符。
最后我们还必须在映射文件里面包括需要持久化属性的声明。缺省的情况下,类里面的属性都被视为非持久化的:
<hibernate-mapping> <class name="Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="increment"/> </id> <property name="date" type="timestamp" column="EVENT_DATE"/> <property name="title"/> </class> </hibernate-mapping>
和id元素类似,property元素的name参数 告诉Hibernate使用哪个getter和setter方法。
为什么date属性的映射包括column参数,但是title却没有? 当没有设定column参数的时候,Hibernate缺省使用属性名作为字段(column)名。对于title,这样工作得很好。 然而,date在多数的数据库里,是一个保留关键字,所以我们最好把它映射成另外一个名字。
下一件有趣的事情是title属性缺少一个type参数。 我们声明并使用在映射文件里面的type,并不像我们假想的那样,是Java data type, 同时也不是SQL database type。这些类型被称作Hibernate mapping types, 它们把数据类型从Java转换到SQL data types。如果映射的参数没有设置的话,Hibernate也将尝试去确定正确的类型转换和它的映射类型。 在某些情况下这个自动检测(在Java class上使用反射机制)不会产生你所期待或者 需要的缺省值。这里有个例子是关于date属性。Hibernate无法知道这个属性应该被映射成下面这些类型中的哪一个: SQL date,timestamp,time。 我们通过声明属性映射timestamp来表示我们希望保存所有的关于日期和时间的信息。
这个映射文件(mapping file)应该被保存为Event.hbm.xml,和我们的EventJava 源文件放在同一个目录下。映射文件的名字可以是任意的,然而hbm.xml已经成为Hibernate开发者社区的习惯性约定。 现在目录应该看起来像这样:
.