ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 1.2.2\. 映射文件 Hibernate需要知道怎样去加载(load)和存储(store)持久化类的对象。这正是Hibernate映射文件发挥作用的地方。映射文件告诉Hibernate它,应该访问数据库(database)里面的哪个表(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里使用它来自动完成那些用来映射的XML元素(element)和属性(attribute)。你也可以在文本编辑器里打开DTD-这是最简单的方式来概览所有的元素和attribute,并查看它们的缺省值以及注释。注意Hibernate不会从web加载DTD文件,但它会首先在应用程序的classpath中查找。DTD文件已包括在`hibernate3.jar`里,同时也在Hibernate发布包的`src/`目录下。 为缩短代码长度,在以后的例子里我们会省略DTD的声明。当然,在实际的应用程序中,DTD声明是必须的。 在`hibernate-mapping`标签(tag)之间, 含有一个`class`元素。所有的持久化实体类(再次声明,或许接下来会有依赖类,就是那些次要的实体)都需要一个这样的映射,来把类对象映射到SQL数据库里的表。 ``` <hibernate-mapping> <class name="events.Event" table="EVENTS"> </class> </hibernate-mapping> ``` 到目前为止,我们告诉了Hibernate怎样把`Events`类的对象持久化到数据库的`EVENTS`表里,以及怎样从`EVENTS`表加载到`Events`类的对象。每个实例对应着数据库表中的一行。现在我们将继续讨论有关唯一标识符属性到数据库表的映射。另外,由于我们不关心怎样处理这个标识符,我们就配置由Hibernate的标识符生成策略来产生代理主键字段。 ``` <hibernate-mapping> <class name="events.Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="native"/> </id> </class> </hibernate-mapping> ``` `id`元素是标识符属性的声明,`name="id"` 声明了Java属性的名字 - Hibernate会使用`getId()`和`setId()`来访问它。 `column`属性则告诉Hibernate, 我们使用`EVENTS`表的哪个字段作为主键。嵌套的`generator`元素指定了标识符生成策略,在这里我们指定`native`,它根据已配置的数据库(方言)自动选择最佳的标识符生成策略。Hibernate支持由数据库生成,全局唯一性(globally unique)和应用程序指定(或者你自己为任何已有策略所写的扩展)这些策略来生成标识符。 最后我们在映射文件里面包含需要持久化属性的声明。默认情况下,类里面的属性都被视为非持久化的: ``` <hibernate-mapping> <class name="events.Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="native"/> </id> <property name="date" type="timestamp" column="EVENT_DATE"/> <property name="title"/> </class> </hibernate-mapping> ``` 和`id`元素一样,`property`元素的`name`属性告诉Hibernate使用哪个getter和setter方法。在此例中,Hibernate会寻找`getDate()/setDate()`, 以及`getTitle()/setTitle()`。 为什么`date`属性的映射含有`column` attribute,而`title`却没有?当没有设定`column` attribute 的时候,Hibernate缺省地使用JavaBean的属性名作为字段名。对于`title`,这样工作得很好。然而,`date`在多数的数据库里,是一个保留关键字,所以我们最好把它映射成一个不同的名字。 另一有趣的事情是`title`属性缺少一个`type` attribute。我们在映射文件里声明并使用的类型,却不是我们期望的那样,是Java数据类型,同时也不是SQL数据库的数据类型。这些类型就是所谓的Hibernate 映射类型_(mapping types)_,它们能把Java数据类型转换到SQL数据类型,反之亦然。再次重申,如果在映射文件中没有设置`type`属性的话,Hibernate会自己试着去确定正确的转换类型和它的映射类型。在某些情况下这个自动检测机制(在Java 类上使用反射机制)不会产生你所期待或需要的缺省值。`date`属性就是个很好的例子,Hibernate无法知道这个属性(`java.util.Date`类型的)应该被映射成:SQL `date`,或`timestamp`,还是`time` 字段。在此例中,把这个属性映射成`timestamp` 转换器,这样我们预留了日期和时间的全部信息。 应该把这个映射文件保存为`Event.hbm.xml`,且就在`Event`Java类的源文件目录下。映射文件可随意地命名,但`hbm.xml`的后缀已成为Hibernate开发者社区的约定。现在目录结构看起来应该像这样: ``` . +lib <Hibernate and third-party libraries> +src +events Event.java Event.hbm.xml ``` 我们继续进行Hibernate的主要配置。