使用Xdoclet和Ant构建Hibernate映射和配置文件
温馨提示:由于文档中含大量图片,这里不方便一一上传建议下载本文电子版文档阅读
Xdoclet.pdf
本文工程下载
svn地址:http://xdocletdemo.googlecode.com/svn/trunk/
功能描述:
在ssh项目中,你是否存在着这样一种困惑,那就是需要手动去配置Hibernate的映射文件和配置文件。这个过程是相当痛苦的,需要写一大堆的的xml文件。Xdoclet就是为了简化这一工作的。它基于Ant或Maven,可以简化你的工作,使你在使用Hibernate时,不用在手动去为每个pojo类写对应的映射文件。当然你可以使用hibernate的注解完成同样的工作,但具体在ssh的项目中到底是选择注解方式还是选择配置方式,这完全取决于你自己或项目经理。关于是否采用注解还是配置文件的来方式来完成hibernate的映射,这个在网上有着很大的争议。这里我不做过多评价。个人更加倾向于使用配置文件。因为配置文件比较灵活,修改后不用重新编译成Java字节码文件,相反使用注解的话你需要及时的去编译。好了,话不多说,我们进入正题。
环境描述:
Eclipse3.6 http://eclipse.org
Ant1.7.1 http://ant.apache.org/
Xdoclet-1.2.3 http://xdoclet.sourceforge.net/xdoclet/index.html
Mysql5.0.22 http://www.mysql.com/
Hibernate3.X http://www.hibernate.org/
WindowsXp sp3
温馨提示:这里重点需要说明一下此处Xdoclet版本为1.2.3,网上有一些关于Xdoclet的配置是基于1.0.4以前的版本。这两个版本之间存在着较大的区别,主要体现在Ant的构建文件build.xml中!请确保你的Xdoclet版本为1.2.3。
Eclipse的安装就不介绍了。
Ant安装:
将下载下来的Ant解压到一个目录(建议该目录不含空格),笔者解压到E:"JAR"apache-ant-1.7.1
Ant解压后的目录结构为:
设置环境变量:
要是Ant能够正常使用,我们需要设置环境变量(通常这是在Windows下)
设置ANT_HOME
修改Path
ANT_HOME
Path
查看环境变量是否设置正确
打开命令行窗口
输入set ANT_HOME查看ANT_HOME
输入set Path查看Path
设置正确后在命令行下输入ant
此时表示已将ant成功安装到操作系统中了,你可以使用ant的各种功能
Xdoclet-1.2.3安装
解压Xdoclet-1.2.3文件
笔者这里解压到E:"JAR"xdoclet"xdoclet-1.2.3
解压后的文件格式为:
这里需要记住xdoclet的解压路径E:"JAR"xdoclet"xdoclet-1.2.3,因为在Ant构建脚本中需要用到它
Mysql的安装不用介绍了,相信大家都不陌生。
准备Hibernate依赖的jar
打开eclipse,创建一个Java工程,名为xdoclet
在工程上右键添加一个名为build.xml的文件
在工程上右键添加一个名为lib的文件夹,拷贝hibernate依赖的jar包及mysql驱动,最后将该lib文件夹设置到classpath路径下
两个实体类一个为Group(组),一个为(User)
为了更好的显示日志信息,添加log4j.properties文件到src路径下
最后你看到的项目结构应该是这样的:
配置实体类
User.java
package com.xdoclet.model;
/**
* @hibernate.class
* table="t_user"
* @author welcome
*
*/
publicclass User {
private String userId;
private String userName;
private Group group;
/**
* @hibernate.id column="userId"
* generator-class="assigned"
*/
public String getUserId() {
returnuserId;
}
publicvoid setUserId(String userId) {
this.userId = userId;
}
/**
* @hibernate.property
*/
public String getUserName() {
returnuserName;
}
publicvoid setUserName(String userName) {
this.userName = userName;
}
/**
* @hibernate.many-to-one
* column="groupId"
* cascade="all"
* class="com.xdoclet.model.Group"
* @param group
*/
public Group getGroup() {
returngroup;
}
publicvoid setGroup(Group group) {
this.group = group;
}
}
|
Group.java
package com.xdoclet.model;
import java.util.Set;
/**
* @hibernate.class
* table="t_group"
* @author welcome
*
*/
publicclass Group {
private String groupId;
private String groupName;
private Set userSets;
/**
* @hibernate.id
* column="groupId"
* generator-class="assigned"
* @return
*/
public String getGroupId() {
returngroupId;
}
publicvoid setGroupId(String groupId) {
this.groupId = groupId;
}
/**
* @hibernate.property
* column="groupName"
* @return
*/
public String getGroupName() {
returngroupName;
}
publicvoid setGroupName(String groupName) {
this.groupName = groupName;
}
/**
* @hibernate.set inverse="true"
* @hibernate.collection-key column="groupId"
* @hibernate.collection-one-to-many
* class="com.xdoclet.model.User"
* @return
*/
public Set getUserSets() {
returnuserSets;
}
publicvoid setUserSets(Set userSets) {
this.userSets = userSets;
}
}
|
注意:实体类中的注解,是xdoclet中的,这里不做解释,具体可以去查看xdoclet关于hibernate的相关文档
http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html
log4j.properties配置文件详情
#All level less than INFO will be logged
log4j.rootLogger=INFO,A1
#A1 is the output device
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.File=e:/log4j.htm
#use html layout
log4j.appender.A1.layout=org.apache.log4j.HTMLLayout
|
此文件会将日志信息记录为html格式的文件,然后输出到E盘下,html格式的日志信息看起来更加舒服。不信你可以去你目录下找找看。
最后我们来关注最重要的文件build.xml
<?xml version="1.0" encoding="UTF-8"?>
<projectname="使用xdoclet映射hibernate"basedir=".">
<!-- 定义源文件目录变量 -->
<propertyname="src.dir"value="${basedir}/src"/>
<!-- 定义xdoclet的目录 -->
<propertyname="xdoclet.home"value="E:/JAR/xdoclet/xdoclet-1.2.3"></property>
<!-- 定义构建路径 -->
<pathid="xdoclet.classpath">
<filesetdir="${xdoclet.home}/lib">
<includename="*.jar"/>
</fileset>
</path>
<pathid="lib.classpath">
<pathelementpath="${java.class.path}"/>
<filesetdir="${xdoclet.home}/lib">
<includename="**/*.jar"/>
</fileset>
<filesetdir="${basedir}/lib">
<includename="**/*.jar"/>
</fileset>
</path>
<!-- 生成Hibernate的映射文件 -->
<targetname="生成Hibernate的映射文件"unless="hibernatedoclet.unnecessary"
description="Generate Hibernate mapping files">
<taskdefname="hibernatedoclet"classname="xdoclet.modules.hibernate.HibernateDocletTask"
classpathref="xdoclet.classpath"/>
<hibernatedocletdestdir="${src.dir}"mergedir="${src.dir}"
excludedtags="@version,@author,@todo,@see"verbose="false">
<filesetdir="${src.dir}">
<includename="com/xdoclet/model/*.java"/>
</fileset>
<hibernateversion="3.0"/>
</hibernatedoclet>
</target>
<!-- 生成Hibernate配置文件 -->
<targetname="生成Hibernate配置文件"depends="生成Hibernate的映射文件">
<taskdefname="hibernatedoclet"classname="xdoclet.modules.hibernate.HibernateDocletTask"
classpathref="xdoclet.classpath"/>
<hibernatedocletdestdir="${src.dir}">
<filesetdir="${src.dir}">
<includename="com/xdoclet/model/*.java"/>
</fileset>
<hibernatecfgdestDir="${src.dir}"version="3.0"
hbm2ddl="create-update"jdbcUrl="jdbc:mysql://localhost:3306/xdoclet"
driver="com.mysql.jdbc.Driver"userName="root"password="root"
dialect="org.hibernate.dialect.MySQL5Dialect"showSql="true">
<otherPropertyname="hbm2ddl"value="create-update"/>
<otherPropertyname="format_sql"value="true"/>
</hibernatecfg>
</hibernatedoclet>
</target>
<!-- 导出数据库表结构 -->
<targetname="导出数据库表结构"depends="生成Hibernate配置文件">
<taskdefname="schemaexport"classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"
classpathref="lib.classpath"/>
<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQL5Dialect"/>
<propertyname="hibernate.format_sql"value="true"/>
<propertyname="hibernate.use_sql_comments true"value="true"/>
<schemaexport
output="schema-export.sql"
quiet="no"
text="yes"
drop="no"
delimiter=";"
>
<filesetdir="${basedir}/src">
<includename="com/xdoclet/model/*.hbm.xml"/>
</fileset>
</schemaexport>
</target>
</project>
|
关于此文件不想做过多解释,细心的朋友可以自己去揣摩,前提是你要有ant的基础知识。
这里需要注意的是这两个元素
<otherProperty name="hbm2ddl" value="create-update" />
<otherProperty name="format_sql" value="true" />
在xdoclet1.0.4以后的版本中hbm2ddl需要以额外的方式来设置,之前我按照1.0.4版本中的方式去设置,此属性死活不会出现在hibernate.cfg.xml中,最后得知这是xdoclet的一个bug
详见:http://jira.codehaus.org/browse/MOJO-466
打开mysql,创建一个名为xdoclet的数据库
在eclipse中运行ant
点window->show view->ant
添加我们的ant脚本到eclipse的ant视图中
点击,选择build.xml文件
在导出数据库表结构上点击run as ant
此时控制台输出:
Buildfile: E:"JAR"jbpm"jbpm-4.3"workspace"xdoclet"build.xml
生成Hibernate的映射文件:
[hibernatedoclet] (XDocletMain.start 47 ) Running <hibernate/>
[hibernatedoclet] Generating mapping file for com.xdoclet.model.Group.
[hibernatedoclet] com.xdoclet.model.Group
[hibernatedoclet] Generating mapping file for com.xdoclet.model.User.
[hibernatedoclet] com.xdoclet.model.User
生成Hibernate配置文件:
[hibernatedoclet] addOtherProperty(): name=null, null
[hibernatedoclet] addOtherProperty(): name=null, null
[hibernatedoclet] (XDocletMain.start 47 ) Running <hibernatecfg/>
[hibernatedoclet] Generating hibernate.cfg.xml configuration file
导出数据库表结构:
[schemaexport] (cfg.Environment 500 ) Hibernate 3.2.0
[schemaexport] (cfg.Environment 533 ) hibernate.properties not found
[schemaexport] (cfg.Environment 667 ) Bytecode provider name : cglib
[schemaexport] (cfg.Environment 584 ) using JDK 1.4 java.sql.Timestamp handling
[schemaexport] (cfg.Configuration 274 ) Reading mappings from file: E:"JAR"jbpm"jbpm-4.3"workspace"xdoclet"src"com"xdoclet"model"Group.hbm.xml
[schemaexport] (cfg.HbmBinder 300 ) Mapping class: com.xdoclet.model.Group -> t_group
[schemaexport] (cfg.Configuration 274 ) Reading mappings from file: E:"JAR"jbpm"jbpm-4.3"workspace"xdoclet"src"com"xdoclet"model"User.hbm.xml
[schemaexport] (cfg.HbmBinder 300 ) Mapping class: com.xdoclet.model.User -> t_user
[schemaexport] (dialect.Dialect 141 ) Using dialect: org.hibernate.dialect.MySQL5Dialect
[schemaexport] (cfg.HbmBinder 2375) Mapping collection: com.xdoclet.model.Group.userSets -> t_user
[schemaexport] (hbm2ddl.SchemaExport 154 ) Running hbm2ddl schema export
[schemaexport] (hbm2ddl.SchemaExport 174 ) writing generated schema to file: E:"JAR"jbpm"jbpm-4.3"workspace"xdoclet"schema-export.sql
[schemaexport]
[schemaexport] alter table t_user
[schemaexport] drop
[schemaexport] foreign key FKCB63CCB6CEAB0634;
[schemaexport]
[schemaexport] drop table if exists t_group;
[schemaexport]
[schemaexport] drop table if exists t_user;
[schemaexport]
[schemaexport] create table t_group (
[schemaexport] groupId varchar(255) not null,
[schemaexport] groupName varchar(255),
[schemaexport] primary key (groupId)
[schemaexport] );
[schemaexport]
[schemaexport] create table t_user (
[schemaexport] userId varchar(255) not null,
[schemaexport] userName varchar(255),
[schemaexport] groupId varchar(255),
[schemaexport] primary key (userId)
[schemaexport] );
[schemaexport]
[schemaexport] alter table t_user
[schemaexport] add index FKCB63CCB6CEAB0634 (groupId),
[schemaexport] add constraint FKCB63CCB6CEAB0634
[schemaexport] foreign key (groupId)
[schemaexport] references t_group (groupId);
[schemaexport] (hbm2ddl.SchemaExport 196 ) schema export complete
BUILD SUCCESSFUL
Total time: 1 second
|
再观察项目目录结构
是不是奇迹出现了?不错,我们做了一大堆工作要的就是这个结果
Group.hbm.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
>
<class
name="com.xdoclet.model.Group"
table="t_group"
>
<id
name="groupId"
column="groupId"
type="java.lang.String"
>
<generator class="assigned">
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-Group.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
</id>
<property
name="groupName"
type="java.lang.String"
update="true"
insert="true"
column="groupName"
/>
<set
name="userSets"
lazy="false"
inverse="true"
cascade="none"
sort="unsorted"
>
<key
column="groupId"
>
</key>
<one-to-many
class="com.xdoclet.model.User"
/>
</set>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-Group.xml
containing the additional properties and place it in your merge dir.
-->
</class>
</hibernate-mapping>
|
User.hbm.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
>
<class
name="com.xdoclet.model.User"
table="t_user"
>
<id
name="userId"
column="userId"
type="java.lang.String"
>
<generator class="assigned">
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-User.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
</id>
<property
name="userName"
type="java.lang.String"
update="true"
insert="true"
column="userName"
/>
<many-to-one
name="group"
class="com.xdoclet.model.Group"
cascade="all"
outer-join="auto"
update="true"
insert="true"
column="groupId"
/>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-User.xml
containing the additional properties and place it in your merge dir.
-->
</class>
</hibernate-mapping>
|
生成的hibernate.cfg.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated file - Do not edit! -->
<hibernate-configuration>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory>
<!-- properties -->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property>
<property name="use_outer_join">false</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/xdoclet</property>
<property name="hbm2ddl">create-update</property>
<property name="format_sql">true</property>
<!-- mapping files -->
<mapping resource="com/xdoclet/model/Group.hbm.xml"/>
<mapping resource="com/xdoclet/model/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
|
是不是跟预期的效果一样呢?
更为激动的是sql脚本
altertable t_user
drop
foreignkey FKCB63CCB6CEAB0634;
droptable if exists t_group;
droptable if exists t_user;
createtable t_group (
groupId varchar(255) notnull,
groupName varchar(255),
primarykey (groupId)
);
createtable t_user (
userId varchar(255) notnull,
userName varchar(255),
groupId varchar(255),
primarykey (userId)
);
altertable t_user
addindex FKCB63CCB6CEAB0634 (groupId),
addconstraint FKCB63CCB6CEAB0634
foreignkey (groupId)
references t_group (groupId);
|
紧接着就来介绍ExportTable.java文件
package com.xdoclet.export;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
public class ExportTable {
public static void main(String[] args) {
Configuration configuration=new Configuration().configure("hibernate.cfg.xml");
SchemaExport export=new SchemaExport(configuration);
export.create(true, true);
}
}
|
很简单,一看就明白了,赶紧run一把吧!
查看生成的数据库表结构
T_user
T_group
哈哈,终于写完了。
现在你可以任意删除*.hbm.xml和hibernate.cfg.xml文件,只需重新运行ant就会再次生成*.hbm.xml和hibernate.cfg.xml文件,是不是很方便?