ITEEDU

19.3. 映射文件生成器(Mapping File Generation)

映射文件的骨架可以从编译过的持久化类中使用MapGenerator工具生成。这工具是Hibernate Extensions发行包的一部分。

Hibernate映射生成器提供了从编译过的类中产生映射的机制。他使用Java反射来查找属性( properties),然后使用启发式算法来从属性类型猜测合适的映射。生成出来的映射文件之应该看作是后续工作的起点。没有办法在没有用户修正的情况下生成完整的Hibernate映射。但是,这个工具还是替你做了很多非常琐碎和麻烦的工作。

类一个一个地加入到映射去。如果工具认为某个类不是Hibernate可持久化( persistable)的,就会把这些类剔除。

判断是否是Hibernate可持久化( persistable)的原则是:

  • 必定不是一个原始类型

  • 必定不是一个数组

  • 必定不是一个接口

  • 必定不是一个内部类

  • 必定有一个默认的无参数的构造方法。

注意,接口和内部类实际上是可以通过Hibernate持久化的,但是一般来说用户不会使用。

对已经发现的类,MapGenerator会重复回溯到超类链条上去,以尽可能的把Hibernate可持久化的超类加入到对同一个数据库表的映射去。如果回溯过程中某个类出现了有个属性在下列备选UID名字(candidate UID names)名单中,回溯就会停止。

默认的备选UID属性名有:uid, UID, id, ID, key, KEY, pk, PK。

如果类中有两个方法,一个是setter,一个是getter,并且setter的单参数的属性和getter的无参数返回值得类型相同,并且setter返回void,就认为发现了一个属性。并且,setter的名字必须以set字符串开始,getter的名字必须以get开始,或者以is开始并且属性类型是boolean。在上面的情况发生时,get和set之后的名字还必须匹配。这个匹配就是属性的名字,然后如果第二个字母是小写的话,会把其首字母变成小写。

用来决定每个属性的数据库类型的规则如下:

  1. 如果Java类型是Hibernate.basic(),则属性是该类型的一个普通字段。

  2. 对于hibernate.type.Type特定类型和PersistentEnum来说,也会使用一个普通字段。

  3. 如果属性类型是一个数组,那么会使用一个Hibernate数组,并且MapGenerator试图反映数组元素的类型。(attempts to reflect on the array element type.)

  4. 如果属性是java.util.List,java.util.Map或者java.util.Set,会使用对应的Hibernate类型,但是MapGenerator不能对这些类型进行进一步处理了。

  5. 如果属性的类型不是上面任何一种,MapGeneraotr把决定数据库类型的步骤留待所有的类都被处理之后再来做。在那时候,如果类在上面描述过的超类搜索过程中被发现了,这个属性会被认为是一个many-to-one的关联。如果类有人和属性,它则是一个组件(component)。否则它就是可序列化的(serializable),或者不是可持久化的。

19.3.1. 运行此工具

这个工具会把XML映射写入到标准输出或者/并且到一个文件中去。

在调用这个工具的时候,你必须把你编译过的类放到classpath中去。

java -cp hibernate_and_your_class_classpaths net.sf.hibernate.tool.class2hbm.MapGenerator options and classnames

有两种操作模式:命令行或者交互式。

交互式模式当你使用一个惟一的命令行参数--interact的时候启动。这个模式提供一个命令控制台。你可以用uid=XXX命令设置每个类的UID属性的名字,XXX就是UID属性名。其他可用的命令就是类名的全限定名,或者“done”命令用来输出XML,并且结束。

在命令行模式下,下面的参数选项和所需处理的类的全限定名可以相互间隔使用。大多数选项会使用多次,每个只影响其后出现的类。

Table 19.7. MapGenerator命令行选项

选项 说明
--quiet 不把O-R 映射输出到stdout
--setUID=uid 设置备选UID名单
--addUID=uid 在备选UID名单前面增加一个新的uid
--select=mode 对后面的classes使用select选择的模式(mode)(比如, distinct 或者all)
--depth=<small-int> 限制后面的类的组件数据递归层数
--output=my_mapping.xml 把O-R 映射输出到一个文件
full.class.Name 把这个类加入到映射中
--abstract=full.class.Name 参见下面的说明

abstract开关指定本工具忽略特定的超类,所以它的继承数上的类不会被映射到一个大表中去。比如,我们来看下面的类继承树:

Animal-->Mammal-->Human

Animal-->Mammal-->Marsupial-->Kangaroo

如果使用--abstract开关,Animal的所有子类都会被放到一个巨大的表中去,包含所有类的所有属性,还有一个用于分辨子类的字段。如果Mammal被标记成abstract,Human和Marsupial会被映射到不同的<class>声明,并且会有各自单独的表。Kangaroo仍然会被认为是Marsupial的子类,除非Marsupial也标记为anstract的。