使用Hibernate的一个不便之处就是要维护数据库schema,hbm文件和java文件的一致性,而Middlegen可以帮助你完成这些。
Middlegen是一个基于Xdoclet的代码,配置文件自动生成工具。它支持目前流行的大部分的技术,例如EJB,JDO,Hibernate,Torque,JSP/Struts等。
Middlegen主要根据你已有的数据库Schema根据你的要求来自动的生成你所需要的文件,这大大的降低了开发难度,提高了开发速度。使用Middlegen的另一个显而易见的好处是你所有的代码可以在一分钟之内和数据库同步。
使用Middlegen自动的生成Hbm文件和Java文件包括两步,第一,根据数据库Schema生成Hbm文件。第二,根据hbm文件生成与之对应得Java文件,这些文件主要是与数据库表对应得持久化类。Middlegen的主要功能都必须在ant环境下使用,下述build文件片断说明了如何定义自定义的任务(task)
<taskdef
name="middlegen"
classname="middlegen.MiddlegenTask"
classpathref="classpath.path"/>
<taskdef
name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask"
classpathref="classpath.path"/>
其中第一个taskdef定义了用于根据数据库schema生成hbm文件的自定义任务(middlegen)。第二个taskdef定义了用于使用hbm文件自动生成持久化Java文件的自定义任务(hbm2java)。其中要说明的是classpath.path指定的路径下必须包含middlegen携带的jar文件和hibernate携带的jar文件。
使用自定义任务来生成hbm文件:
<target name="mid-gen" depends="mid-init">
<taskdef
name="middlegen"
classname="middlegen.MiddlegenTask"
classpathref="classpath.path"/>
<middlegen appname="mda"
prefsdir="${conf.dir}"
gui="false"
databaseurl="${config.database.url}"
driver="oracle.jdbc.driver.OracleDriver"
username="${config.database.user}"
password="${config.database.password}"
schema="${config.database.user}"
includeViews="false">
<hibernate destination="${build.src-gen.dir}"
package="entity"
genXDocletTags="true" javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"/>
</middlegen>
</target>
上述build片断中middlegen部分主要说明了在使用middlegen过程中的一些配置,关于数据库部分不用多说,主要说明gui和prefsdir部分。Middlegen自带了一个GUI界面用来即时的变更数据库字段和生成文件之间的映射关系,如果将gui属性设置为true,那么在代码生成之前会跳出一个界面让你来配置数据库字段和生成文件之间的对应关系,但是对于每日构建来说这不太合适,应为这个过程序要人为的干涉,哪怕只是点击确认按钮。同时middlegen提供了一个prefsdir选项,middlegen会自动地在该选项指定的目录下寻找文件appname-prefs.properties,根据该文件中定义的对应关系来生成文件。其中appname就是上述定义的appname,本例中为mda-prefs.propertyes。
hibernate部分主要说明生成hbm文件的一些属性,例如destination说明了生成文件的位置。Package说明了生成hbm文件对应的java文件的所在包。GenXDocletTags说明了是否在hbm文件内部保留元数据标记。
如下是一个mda-prefs.propertyes文件的一部分:
hibernate.tables.GENINKBNINFO.base-class-name=GeninKbnInfoEntity
hibernate.tables.GENINKBNINFO.columns.GENINKBN.java-name=geninKbn
hibernate.tables.GENINKBNINFO.columns.GENINKBN.java-type=java.lang.String
hibernate.tables.GENINKBNINFO.columns.GENINKBNCD.java-name=geninKbnCD
hibernate.tables.GENINKBNINFO.columns.GENINKBNCD.java-type=java.lang.Integer
…
以上说明对于数据库中的表GENINKBNINFO对应的Java类为GeninKbnInfoEntity,该表有两个字段:GENINKBN和GENINKBNCD,其中字段GENINKBN对应的java字段的属性名为geninKbn,类型为String。字段GENINKBNCD对应得java字段属性名为geninKbnCD,类型为Integer,生成的hbm文件为:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<!--
Created by the Middlegen Hibernate plugin 2.1
http://boss.bekk.no/boss/middlegen/
http://www.hibernate.org/
-->
<class
name="entity.GeninKbnInfoEntity"
table="GENINKBNINFO"
>
<meta attribute="class-description" inherit="false">
@hibernate.class
table="GENINKBNINFO"
</meta>
<id
name="geninKbnCD"
type="java.lang.Integer"
column="GENINKBNCD"
>
<meta attribute="field-description">
@hibernate.id
generator-class="assigned"
type="java.lang.Integer"
column="GENINKBNCD"
</meta>
<generator class="assigned" />
</id>
<property
name="geninKbn"
type="java.lang.String"
column="GENINKBN"
not-null="true"
length="40"
>
<meta attribute="field-description">
@hibernate.property
column="GENINKBN"
length="40"
not-null="true"
</meta>
</property>
<!-- Associations -->
</class>
</hibernate-mapping>
然后使用如下build片断来根据hbm文件自动生成java文件。
<target name="hbm2java"
description="Generate .java from .hbm files." depends="mid-gen">
<taskdef
name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask"
classpathref="classpath.path"/>
<hbm2java output="${build.src-gen.dir}" classpathref="classpath.path">
<fileset dir="${build.src-gen.dir}">
<include name="**/*.hbm.xml"/>
</fileset>
</hbm2java>
</target>
hbm2java是hibernate自带的一个工具你必须从hibernate网站上下载一个叫做hibernate-tools.jar的工具,并且将它加载到classpath下面,如下是该工具生成的Java代码:
package entity;
import java.io.Serializable;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
* @hibernate.class
* table="GENINKBNINFO"
*
*/
public class GeninKbnInfoEntity implements Serializable {
/** identifier field */
private Integer geninKbnCD;
/** persistent field */
private String geninKbn;
/** full constructor */
public GeninKbnInfoEntity(Integer geninKbnCD, String geninKbn) {
this.geninKbnCD = geninKbnCD;
this.geninKbn = geninKbn;
}
/** default constructor */
public GeninKbnInfoEntity() {
}
/**
* @hibernate.id
* generator-class="assigned"
* type="java.lang.Integer"
* column="GENINKBNCD"
*
*/
public Integer getGeninKbnCD() {
return this.geninKbnCD;
}
public void setGeninKbnCD(Integer geninKbnCD) {
this.geninKbnCD = geninKbnCD;
}
/**
* @hibernate.property
* column="GENINKBN"
* length="40"
* not-null="true"
*
*/
public String getGeninKbn() {
return this.geninKbn;
}
public void setGeninKbn(String geninKbn) {
this.geninKbn = geninKbn;
}
public String toString() {
return new ToStringBuilder(this)
.append("geninKbnCD", getGeninKbnCD())
.toString();
}
public boolean equals(Object other) {
if ( !(other instanceof GeninKbnInfoEntity) ) return false;
GeninKbnInfoEntity castOther = (GeninKbnInfoEntity) other;
return new EqualsBuilder()
.append(this.getGeninKbnCD(), castOther.getGeninKbnCD())
.isEquals();
}
public int hashCode() {
return new HashCodeBuilder()
.append(getGeninKbnCD())
.toHashCode();
}
}
生成的java文件中带有Xdoclet标签,完全可以在从Java文件生成Hbm文件,这里不讲具体的过程,可以参看后续的Xdoclet部分。