· velocity-tools-generic-1.4.jar · jtidy-r8-21122004.jar · hibernate3.jar · JDBC drivers
这样一来,Ant任务就要作如下申明:
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="maven.dependency.classpath"/>
最后,你在hibernatetool 任务中调用hbm2java任务,做法如下:
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="maven.dependency.classpath"/>
<hibernatetool destdir="src/main/generated/src/java"> <configuration configurationfile="src/main/hibernate/hibernate.cfg.xml"> <fileset dir="src/main/hibernate"> <include name="**/*.hbm.xml"/> </fileset> </configuration>
<hbm2java /> </hibernatetool>
注意:尽管Hibernate 3版的工具是很有前途的,但它仍只是在alpha阶段,因此使用时务必小心为是。(译注:翻译此文时最新的Hibernate版本是3.1.2,Hibernate Tools的版本是3.1 beta 4)
定制生成的Domain类
现在你知道了怎样从Hibernate映射生成Java源代码, 那么下一步呢?为了更加具体地讨论,我们将使用如图2 和3所描述的简单类模型。这个类模型表示Employee数据库。每个employee赋予一country,讲一种或多种language。每个country 也有一组国际机场(airport)。
图2. 示例应用程序的UML类图
图3. 示例中所用的数据库模式
有时,你可能想添加域逻辑到Domain类中。实际上,对多数人来说,生成Java类的主要缺点是Domain类变得相对被动,而且把业务逻辑方法加入生成的Domain类中并不容易,就如所论证的那样使它们更不接近“面向对象“。对这问题并没有一个万能的解决方案,但我们在此描述了一些可能的方法。
把代码放入映射文件: class-code元属性(meta attribute)
对于简单的方法,你可以用class-code元属性来在Hibernate映射文件中指定额外的Java代码。例如,假设我们想在country和airports间建立双向关系。只要我们想增加airport属性到Country 对象,我们就要确定在Airport对象中相应地增加country属性。我们可以这么做:
<class name="Country" table="COUNTRY" dynamic-update="true"> <meta attribute="implement-equals">true</meta> <meta attribute="class-code"> <![CDATA[ /** * Add an airport to this country */ public void addAirport(Airport airport) { airport.setCountry(this); if (airports == null) { airports = new java.util.HashSet(); } airports.add(airport); } ]]> </meta>
<id name="id" type="long" unsaved-value="null" > <column name="cn_id" not-null="true"/> <generator class="increment"/> </id>
<property column="cn_code" name="code" type="string"/> <property column="cn_name" name="name" type="string"/>
<set name="airports" > <key column="cn_id"/> <one-to-many class="Airport"/> </set> </class>
除了那些非常小的方法,这种做法并不是特别地令人满意:在XML文件里编写Java代码的做法很容易出错而且难于维护。 使用SQL表达式有时业务逻辑(特别地如果引入了聚合,求和,合计等运算)可能会更自然地用SQL表达式来定义:
<property name="orderTotal" type="java.lang.Double" formula="(select sum(item.amount) from item where item.order_id = order_id)" />
在多数情况下这是非常好的解决方案。但是,必须注意的是每次Hibernate从数据库加载对象时都会执行查询的动作,这可能会对性能造成影响。
使用基类
你也可以用generated-class元属性来定义基类,hbm2java会用这些元属性生成基类,这样你就可以在所生成基类的子类中自由地添加业务逻辑。例如,我们可以在Country类上应用这种技术,就象下面所描述的:
<class name="Country" table="COUNTRY" dynamic-update="true"> |