使用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文件,是不是很方便?