在NetBeans5.0中使用xdoclet生成hibernate的*.hbm.xml文件
敬告:
------------------------------------------------------------
本文作者希望本文可以在网络及任何媒体进行任何形式的传播、复
制、引用、修改,在此过程中请保留此敬告内容。
谢谢!
popo
------------------------------------------------------------
NetBeans是基于ANT进行项目的build和run的,所以我们可以方便的加入自己的target对原有项目进行扩展。
启动NetBeans,打开以前写的SimpleWebSite_dao项目,因为我们要做的是利用XDoclet生成Hibernate的*.hbm.xml(ORM)文件,所以将XDoclet的所有Jar包解压到lib\xdoclet-1.3-SNAPSHOT目录下,不用在项目中引用XDoclet的包,因为我们是要通过修改Build文件来引用这些包。
选择“Files”窗口,展开SimpleWebSite_dao项目。
打开build.xml文件,看该文件中的注释,大概就是讲NetBeans为我们生成的build文件是nbproject/build-impl.xml,build.xml已经import了build-impl文件,如果我们想加入自己的target或者对原有target进行修改,只要改动build文件就可以。
用NetBeans编辑XML文件很方便,可以对XML文件进行检查和校验,并且还有代码提示及补齐的功能:)。导航窗口更是为我们查看XML内容结构提供了极大的方便。
在build.xml中加入以下内容:
<property name="lib.dir" location="../lib" />
<property name="xdoclet.dir" location="../lib/xdoclet-1.3-SNAPSHOT" />
<path id="xdoclet.classpath">
<fileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${xdoclet.dir}" includes="*.jar"/>
</path>
<!-- =================================================================== -->
<!-- The "hibernatedoclet" target generates Hibernate mapping files -->
<!-- based on XDoclet marked-up Plain Old Java Object (POJO) -->
<!-- =================================================================== -->
<target name="hibernatedoclet" depends="compile" unless="hibernatedoclet.unnecessary"
description="Generate Hibernate mapping files">
<taskdef name="hibernatedoclet"
classname="xdoclet.modules.hibernate.HibernateDocletTask"
classpathref="xdoclet.classpath"/>
<!-- generate hibernate files -->
<hibernatedoclet destdir="${build.classes.dir}" mergedir="${build.classes.dir}"
excludedtags="@version,@author" addedtags="@xdoclet-generated at ${TODAY}"
force="${xdoclet.force}">
<fileset dir="src"/>
<hibernate validatexml="true" version="3.0"/>
</hibernatedoclet>
</target>
用右键点build.xml文件,在“Run target”中,会看到我们新加的target->“hibernatedoclet”。
现在写一个POJO,用这个target生成.hbm.xml文件。
New 一个Java Class Customer(这个类的代码是从网上拷贝来的,因为我对XDoclet还不太熟悉):
package hibernate;
import java.util.Set;
import java.util.Collections;
/**
* @author roson
* @since 1.0
* @version 1.0
* @hibernate.class tables="customers"
*/
public class Customer {
/**This customer's identifier field.
*/
private long id;
/**This customer's name field.
*/
private String name;
/**The customer's orders set.
*/
private Set orders=Collections.EMPTY_SET;
/**The default construtor for Hibernate to instantiate with.
*/
public Customer() {}
/**The getter method for this Customer's identifier.
*
* @hibernate.id generator-class="native"
*/
public long getId() {
return id;
}
/**The setter method for this Customer's identifier.
*/
public void setId(long id) {
this.id=id;
}
/**The getter method for this Customer's name.
*
* @hibernate.property
*/
public String getName() {
return name;
}
/**The setter method for this Customer's name.
*/
public void setName(String name) {
this.name=name;
}
/**The getter method for this Customer's orders.
*
* @hibernate.set role="orders"
*
* @hibernate.collection-key column="customer_id"
*
* @hibernate.collection-one-to-many class="Order"
*/
public Set getOrders() {
return orders;
}
/**The setter method for this Customer's orders.
*/
public void setOrders(Set orders) {
this.orders=orders;
}
}
现在右键点build.xml文件,在“Run target”中,选“hibernatedoclet”,BUILD SUCCESSFUL。
在build\classes\hibernate目录下会看到编译后的Customer.class文件和XDoclet生成的Customer.hbm.xml。
为了方便,我们进一步修改build.xml文件,将build-impl.xml中的“jar”这个target复制粘贴过来,并改为以下内容:
<target name="jar" depends="init,hibernatedoclet,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR."/>
我只把depends中的compile改为了hibernatedoclet,这样在编译后和打包前的时候,会生成*.hbm.xml文件。
现在的build.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="SimpleWebSite_Dao" default="default" basedir=".">
<description>Builds, tests, and runs the project SimpleWebSite_Dao.</description>
<import file="nbproject/build-impl.xml"/>
<property name="lib.dir" location="../lib" />
<property name="xdoclet.dir" location="../lib/xdoclet-1.3-SNAPSHOT" />
<path id="xdoclet.classpath">
<fileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${xdoclet.dir}" includes="*.jar"/>
</path>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="SimpleWebSite_Dao-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
<!-- =================================================================== -->
<!-- The "hibernatedoclet" target generates Hibernate mapping files -->
<!-- based on XDoclet marked-up Plain Old Java Object (POJO) -->
<!-- =================================================================== -->
<target name="hibernatedoclet" depends="compile" unless="hibernatedoclet.unnecessary"
description="Generate Hibernate mapping files">
<taskdef name="hibernatedoclet"
classname="xdoclet.modules.hibernate.HibernateDocletTask"
classpathref="xdoclet.classpath"/>
<!-- generate hibernate files -->
<hibernatedoclet destdir="${build.classes.dir}" mergedir="${build.classes.dir}"
excludedtags="@version,@author" addedtags="@xdoclet-generated at ${TODAY}"
force="${xdoclet.force}">
<fileset dir="src"/>
<hibernate validatexml="true" version="3.0"/>
</hibernatedoclet>
</target>
<target name="jar" depends="init,hibernatedoclet,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR."/>
</project>
在Projects窗口,选“Build Project”或者“Clean and Build Project”,
会看到用到了我们修改后的jar这个target进行的编译和打包。
XDoclet的功能很强大,我会边学边在我的项目中利用它,可以省去很多编码工作。
看Appfuse的build.xml,数据库的表是用Hibernate提供的SchemaExportTask工具生成数据库建表的SQL,我们也来照做,这样只要在写POJO时加上注释,用ANT的target就可以生成*.hbm.xml文件和创建数据表的SQL语句。方便吧?
对build.xml进行修改,把生成*.hbm.xml文件的目标路径改为SRC目录,不再depends="compile",改为在jar的时候先“hibernatedoclet”再“compile”,增加create_tables_sql的target,修改后的build.xml文件为:
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="SimpleWebSite_Dao" default="default" basedir=".">
<description>Builds, tests, and runs the project SimpleWebSite_Dao.</description>
<import file="nbproject/build-impl.xml"/>
<property name="src.dir" location="./src" />
<property name="lib.dir" location="../lib" />
<property name="xdoclet.dir" location="../lib/xdoclet-1.3-SNAPSHOT" />
<path id="xdoclet.classpath">
<fileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${xdoclet.dir}" includes="*.jar"/>
</path>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="SimpleWebSite_Dao-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
<!-- =================================================================== -->
<!-- The "hibernatedoclet" target generates Hibernate mapping files -->
<!-- based on XDoclet marked-up Plain Old Java Object (POJO) -->
<!-- =================================================================== -->
<target name="hibernatedoclet" unless="hibernatedoclet.unnecessary"
description="Generate Hibernate mapping files">
<taskdef name="hibernatedoclet"
classname="xdoclet.modules.hibernate.HibernateDocletTask"
classpathref="xdoclet.classpath"/>
<!-- generate hibernate files -->
<hibernatedoclet destdir="${src.dir}" mergedir="${src.dir}"
excludedtags="@version,@author" addedtags="@xdoclet-generated at ${TODAY}"
force="${xdoclet.force}">
<fileset dir="${src.dir}"/>
<hibernate validatexml="true" version="3.0"/>
</hibernatedoclet>
</target>
<!-- =================================================================== -->
<!-- The "create_tables_sql" target generates the database schema and -->
<!-- creates tables based on the mapping files -->
<!-- =================================================================== -->
<target name="create_tables_sql" depends="hibernatedoclet" description="creates database tables">
<taskdef name="schemaexport"
classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"
classpathref="xdoclet.classpath"/>
<schemaexport quiet="yes" text="true" drop="no" delimiter=";"
properties="src/database.properties" output="../database/sql/create-tables.sql">
<fileset dir="${src.dir}" includes="**/*.hbm.xml"/>
</schemaexport>
</target>
<target name="jar" depends="init,create_tables_sql,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR."/>
</project>
这样,每次“Build Project”或者“Clean and Build Project”时,都会先在源程序目录创建*.hbm.xml文件,再在../database/sql目录下生成创建数据表的SQL文件,再进行编译,打包。
用上面的示例文件有几个问题
1.Customer类中 * @hibernate.class tables="customers"应该是 * @hibernate.class table="customers",
2.生成的Customer.hbm.xml文件“create_tables_sql”时失败,提示信息为:
D:\ProjectNetBeans\SimpleWebSite\SimpleWebSite_Dao\build.xml:107: Schema text failed: Could not read mapping document from file: D:\ProjectNetBeans\SimpleWebSite\SimpleWebSite_Dao\src\hibernate\Customer.hbm.xml
BUILD FAILED (total time: 4 seconds)
为字段加上数据类型(type="java.lang.Long")后可以读取文件,但还是失败:
D:\ProjectNetBeans\SimpleWebSite\SimpleWebSite_Dao\build.xml:107: Schema text failed: Association references unmapped class: Order
因为对XDoclet不熟,对Hibernate的配置也快忘记差不多了,所以省点事儿,先把Order属性去掉。
“Clean and Build Project”,哈哈,看看,*.hbm.xml文件和建数据库表的Sql语句都生成啦。
不过还没有试过Debug等target,如果那些target依赖生成的*.hbm.xml文件的话,还要对相应的target加上depends...
剩下的就是要多看看XDoclet和Hibernate配置的文档啦。