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