(2006.08月號--151期) 如何以Maven協助Hibernate開發
在今日的企業級應用開發環境中,物件導向開發方式已成為主流,但在實際的應用中,物件只存在於程式與記憶體之中,並不能直接進行儲存。如果想要永久保存物件狀態,則必須要進行物件的持久化,也就是把物件狀態儲存進專門的資料庫系統中,而目前最廣泛使用的關聯式資料庫(RDBMS),並不支援儲存物件導向數據資料。
因此傳統的關聯式資料庫程式設計,必須直接在程式中以Hard code的方式撰寫SQL語法進行開發,而以Hard code撰寫SQL語法的方式,相對的也代表了開發的應用程式無法跨資料庫平台。雖然JDBC統一了Java程式與資料庫之間的操作介面,讓開發人員可以不用了解與資料庫相關特定的API操作,然而自行撰寫SQL語法或再次將SQL語法進行封裝仍是不可避免的事,而在物件導向程式設計之中,物件與關聯式資料並無法以簡單的方式進行轉換,導致了資料永續性的開發上受到了先天的限制。
ORM(Object/Relational Mapping)物件-關聯映射技術,在該問題的處理上已經有完善的解決方案,而目前在開放原始碼的技術中,最受人矚目的ORM實作,應該就是Hibernate了。在本期中筆者將介紹如何使用Maven協助Hibernate進行快速開發,而對於Hibernate的基本觀念,筆者在此並不詳述,請參考之前刊載於RunPC中的相關文章。
註:關於Hibernate文章,請參考RunPC於128、129、130、132期,資料永續層解決方案Hibernate的相關介紹,作者為Mark Ho。
設定hibernatedoclet環境
在開發過程中Hibernate進行物件與關聯式資料的處理過程中,需要有一份映射文件,用以描述物件與關聯式資料的轉換關係,例如:資料型態的對應、資料欄位長度的限制、單向關聯、雙向關聯、一對多、一對一與多對多關聯等等的設定。一般而言映射文件命名通常為*.hbm.xml。
然而在實際開發上當物件作了修改或重構後,必須對映射文件進行維護。如此的開發方式相當的不直覺與不方便。並且學習映射文件的撰寫不是一件簡單的事。
因此我們換一個角度思考,如果在物件的設計中,順手將這些轉換關係的資訊寫在物件中,由物件編譯過程中直接幫我們產生相關的映射文件,則我們只要維護一份原始碼即可,當進行修改與重構的過程中,映射檔案的變更也將立即的反應出來。在此我們將使用XDoclet進行Code generate來達到這個目的。
註:有關於XDoclet相關觀念的文章,請參考RunPC於130、131期,XDoclet入門篇與進階篇,作者為歐宣修。
首先請參考筆者於148期中的Maven文章,使用Maven Genapp Plugin產生專案,並且參考設定 1將project.xml進行修改,在該檔中可以看到我們在Maven相依的plugin套件中加入了maven-xdoclet-plugin。接著參考設定 2對 project.properties加入設定參數。說明請參考表 1中關於hibernatedoclet的參數設定。最後再對maven.xml進行設定,參考設定 3中可知當我們執行java:compile這個goal前會先行運作xdoclet:hibernatedoclet協助我們產生Mapping file。
<?xml version="1.0" encoding="UTF-8"?>
<project>
<pomVersion>3</pomVersion>
<artifactId>hibernate-example</artifactId>
<groupId>hibernate-example</groupId>
<name>Example Hibernate Application</name>
<currentVersion>1.0</currentVersion>
<dependencies>
<dependency>
<groupId>xdoclet</groupId>
<artifactId>maven-xdoclet-plugin</artifactId>
<version>1.2.3</version>
<type>plugin</type>
</dependency>
…中間省略…
</dependencies>
…中間省略…
</project>
#####################################
# hibernatedoclet properties
#####################################
maven.xdoclet.hibernatedoclet.fileset.0=true
maven.xdoclet.hibernatedoclet.fileset.0.sourcedir=${maven.src.dir}/java
maven.xdoclet.hibernatedoclet.fileset.0.include=**/*.java
maven.xdoclet.hibernatedoclet.fileset.0.exclude=
maven.xdoclet.hibernatedoclet.hibernate.0=true
maven.xdoclet.hibernatedoclet.hibernate.0.Version=3.0
maven.xdoclet.hibernatedoclet.destDir=${maven.build.dest}
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns:j="jelly:core"
xmlns:ant="jelly:ant">
<preGoal name="java:compile">
<attainGoal name="xdoclet:hibernatedoclet"/>
</preGoal>
</project>
參數 | 說明 |
maven.xdoclet.hibernatedoclet.fileset.[index] | 設定hibernatedoclet引用的檔案集設定,index值為0~9共10組設定,也就是說最多可以針對10組路徑下的原始檔進行hibernatedoclet的Code generate,預設index=0為啟用。若指定的maven.xdoclet.hibernatedoclet.fileset.[index]未設定,則以下相對應的檔案集設定即無效。 |
maven.xdoclet.hibernatedoclet.fileset.[index].sourcedir | 指定檔案集原始碼放置路徑,預設為${maven.src.dir}/java |
maven.xdoclet.hibernatedoclet.fileset.[index].include | 指定檔案集引入檔案規則,預設為**/*.java |
maven.xdoclet.hibernatedoclet.fileset.[index].exclude | 指定檔案集排除檔案規則,預設不排除任何檔。 |
maven.xdoclet.hibernatedoclet.hibernate.[index] | 設定對maven.xdoclet.hibernatedoclet.fileset.[index]進行hibernatedoclet是否生效,預設為true,若為false則對指定的檔案集不執行hibernatedoclet。 |
maven.xdoclet.hibernatedoclet.hibernate.[index].Version | 設定對maven.xdoclet.hibernatedoclet.fileset.[index]進行hibernatedoclet所產生的*.hbm.xml檔案可使用於hibernate那個版本,預設為1.1版,目前可設定的值為目前有1.1、 2.0、2.1、3.0。 |
maven.xdoclet.hibernatedoclet.destDir | 所有檔案集產生出的*.hbm.xml放置的目的路徑。 |
建立Domain Object並產生Mapping File
當上一節的設定完成後,我們正式建立Domain Object,並試圖產生Hibernate所需要的Mapping file。這裏我們
是以POJO定義Domain Object,而POJO就是所謂的Plain Ordinary Java Object,字面上來講就是無格式普通Java 物件,簡單的可以理解爲一個不包含邏輯程式碼的值物件。
我們在此建立二個POJO,分別是User(使用者)與Role(所屬角色)作為開始。這時Maven專案架構應該如資料結構 1所示,圖 1展示了類別屬性與其set、get相關method。接著參考程式 1、程式 2分別在類別中加入<hibernatedoclet>Tag設定,在此我們簡單的了解一下相關屬性用途,若讀者希望了解更詳細的屬性設定,可參考XDoclet官方網站http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html。
-
@hibernate.class:該Tag用於宣告定義持久化類別,需放置於Class宣告的上方。
-
table:指定持久化類別對應資料庫Table名稱。
-
-
@hibernate.id:定義主鍵欄位相關屬性。
-
column:指定欄位對應資料庫欄位名稱,若未指定則使用相對應的property名稱。
-
generator-class:主鍵產生器屬性,目前有uuid.hex、uuid.string、increment、assigned、native、identity、sequence、hilo、seqhilo、foreign可供設定。
-
-
@hibernate.property:定義持久化類別對應資料庫欄位相關屬性。
-
column:指定欄位對應資料庫欄位名稱,若未指定則使用相對應的property名稱。
-
length:指定對應資料庫欄位長度。
-
not-null:是否允許欄位存放null值。
-
unique:是否允許資料庫欄位值重覆
-
type:對應資料庫欄位型態
-
另外,讀者可能發現,在範例中的二個POJO都實現了java.io.Serializable介面,這是Hibernate規範中所提到的,但目前大多數資料並未說明為何必須實現Serializable。事實上Hibernate並不要求持久化類必須實現Serializable介面,但是對於採用分散式架構的Java應用,當Java物件在不同的分散節點之間傳輸時(例如:RMI),這個物件所屬的類別必須實現Serializable介面,此外,在Java Web應用中,如果希望對HttpSession中存放的Java物件進行持久化,那麼這個Java物件所屬的類也必須實現Serializable介面,因此若只拿Hibernate作單純資料庫應用可不遵守該規定外,Hibernate在J2EE的應用上都是必須實現Serializable的。
經過maven的設定與撰寫完POJO後,在Console下執行maven java:compile,當指令運作結束後,在[hibernate_example/target/classes/demo/model]路徑下將會出現User.hbm.xml與Role.hbm.xml的Hibernate Mapping file。
hibernate-example
|--src
| --main
| --java
| --demo
| --model
| |--Role.java
| --User.java
|--maven.xml
|--project.properties
--project.xml
package demo.model;
import java.io.Serializable;
/**
* @hibernate.class table="app_user"
*/
public class User implements Serializable {
private Long id;
private String username;
private String password;
/**
* @hibernate.id column="id" generator-class="native"
*/
public Long getId() {
return id;
}
/**
* @hibernate.property length="50" not-null="true" unique="true"
*/
public String getUsername() {
return username;
}
/**
* @hibernate.property column="password" not-null="true"
*/
public String getPassword() {
return password;
}
…set method 省略…
}
package demo.model;
import java.io.Serializable;
/**
* @hibernate.class table="role"
*/
public class Role implements Serializable {
private Long id;
private String name;
private String description;
/**
* @hibernate.id column="id" generator-class="native"
*/
public Long getId() {
return id;
}
/**
* @hibernate.property column="name" length="20"
*/
public String getName() {
return name;
}
/**
* @hibernate.property column="description" length="64"
*/
public String getDescription() {
return description;
}
…set method 省略…
}
使用Hibernate Plugin建立Table Schema
到目前為止我們設定了hibernatedoclet、建立了POJO的類別並自動產生了相關的Mapping file。假設這時資料庫Schema早已建立好的話,就可以開始使用Hibernate進行DAO的開發與測試了。倘若Schema尚未建立呢?需要自行建立嗎?而自行建立則又會引發另一個問題,POJO的設計是基於Schema所建立的。當日後Schema修改時也必須對應相關的POJO或Mapping file進行維護。一次、二次還可以接受,但在專案開發的過程中需求永遠在變化,很難保證Schema不會一直變更,一旦次數一多,將引發難以重構的災難。
在Ant中可以透過net.sf.hibernate.tool.hbm2ddl.SchemaExportTask協助我們將*.hbm.xml再次轉化成相對應資料庫的Schema,而在Maven上可以使用Hibernate Plugin協助進行SchemaExport。基於某些因素Hibernate Plugin最新版本為1.3並且已有一段時間沒有新版本釋出,該版本並未支援Hibernate 3.X,若讀者使用Hibernate 2開發的話,可以直接進行下載。在本次範例中我們將下載經過1.3版本修改的Hibernate Plugin1.4 (請讀者參考相關資源4進行下載)。
將[%MAVEN_HOME%/plugins]下的1.3版移除,放置下載完成的maven-hibernate-plugin-1.4.jar於該資料夾內即完成了hibernate plugin的安裝。接著參考設定 4在project.xml中加入相依套件,此處的設定中我們加入了maven-hibernate-plugin的設定與Hibernate進行SchemaExport時所需的套件,另外為了示範Hibernate跨資料庫平台的特色,在此引入而PostgreSql與Hsqldb二個開放原始碼資料庫的JDBC協助進行測試。
在進行SchemaExport功能時可以設定是否正式進行資料庫的更新,或者只是單純的產生資料庫Schema的文字檔供開發人員進行修改或使用。為此必須正確設定Hibernate與資料庫連結的相關參數,參考設定 5與設定 6比較範例中二種資料庫設定的異同處,而關於hibernate.dialect參數的設定,請參考Hibernate官方參考手冊。
最後參考設定 7加入Hibernate plugin所需的參數,讀者對照表 2即可知相關參數的意義為何。當設定完成後於Console下執行maven hibernate:schema-export即可進行SchemaExport,在此我們分別為了PostgreSql與Hsqldb作了SchemaExport,請參考圖 2與圖 3的結果。若讀者不希望直接進行資料庫的更新,則可將project.properties檔中參數maven.hibernate.text設為yes再次進行hibernate:schema-export,即可於[target/schema/schema.sql]檔中查看匯出的資料庫SQL語法。
hibernate:schema-export這個goal可以協助我們進行建立資料庫Schema,而當進行POJO的修改並重新產生Mapping file時,可運行maven hibernate:schema-update,該指令將可在不移除資料表的清況下進行資料庫Schema的更新,對於DataBase Schema的重構有很大的幫助。
<dependency>
<groupId>maven</groupId>
<artifactId>maven-hibernate-plugin</artifactId>
<version>1.4</version>
<type>plugin</type>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.1-407.jdbc3</version>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.7.3.3</version>
</dependency>
<dependency>
<groupId>geronimo-spec</groupId>
<artifactId>geronimo-spec-jta</artifactId>
<version>1.0.1B-rc4</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.0.5</version>
</dependency>
設定 5 database-postgresql.properties
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.connection.url=jdbc:postgresql://localhost/demo
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.connection.show_sql=true
hibernate.connection.username=test
hibernate.connection.password=test
設定 6 database-hsqldb.properties
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.connection.url=jdbc:hsqldb:hsql://localhost/demo
hibernate.connection.driver_class=org.hsqldb.jdbcDriver
hibernate.connection.show_sql=true
hibernate.connection.username=sa
hibernate.connection.password=
設定 7 project.properties增添相關屬性設定
#####################################
# hibernate properties
#####################################
maven.hibernate.properties=${basedir}/database-postgresql.properties
#maven.hibernate.properties=${basedir}/database-hsqldb.properties
maven.hibernate.quiet=no
maven.hibernate.text=no
maven.hibernate.drop=no
maven.hibernate.delimiter=;
maven.hibernate.output.dir=${maven.build.dir}/schema
maven.hibernate.output.file=${maven.hibernate.output.dir}/schema.sql
參數 | 說明 |
maven.hibernate.properties | hibernate參數設定檔放置路徑,無論直接進行資料庫的更新或單純產出Schema的文字檔,皆必須要進行該項設定主要以hibernate.dialect參數決定使用何種資料庫方言。 |
maven.hibernate.text | 若為yes則執行Schema Export時將直接匯出SQL成文字檔,並不會進行資料庫的更新,若設為no則直接進行資料庫Schema的更新,預設為no |
maven.hibernate.quiet | 是否顯示詳細的Schema Export資訊,例:當maven.hibernate.text=no,maven.hibernate.quiet=yes時,將直接進行資料庫Schema的更新,Console下不會顯示任何訊息,預設為yes |
maven.hibernate.drop | 是否只執行drop資料表的動作,若maven.hibernate.text=yes則匯出SQL檔將只包含drop table的SQL語法。 |
maven.hibernate.delimiter | 分隔SQL Commands的定義符號,預設值為空字串,而大多數狀況使用”;”作為分隔符號。 |
maven.hibernate.output.dir | 若maven.hibernate.text=yes,匯出檔放置資料夾,預設為${maven.build.dir}/schema |
maven.hibernate.output.file | 若maven.hibernate.text=yes,匯出檔放置路徑,預設為${maven.hibernate.output.dir}/${maven.final.name}-schema.sql |
結論
Hibernate是一個開放原始碼的物件關聯映射技術,針對了JDBC進行了輕量化的將關聯資料轉化為物件封裝,使得開發人員可以隨心所欲的使用物件導向思維來駕馭資料庫。而在本期的介紹中我們了解了使用Maven協助Hibernate建立Domain Object的一種應用,而除了本次範例的方式外,Hibernate也可以使用Middlegen的方式透過現有的資料庫Schema產生出Mapping file,又或著從Mapping file建立出Schema與Java Domain Object。因此可依專案的狀況進行彈性的調整。
Hibernate的應用可以切入在任何使用JDBC的場合,既可以應用於單純的Java Application,也可以在Servlet/JSP的Web應用程式中使用,更可以應用在EJB的J2EE架構中取代CMP,完成資料持久化的重任。倘若更深入Hibernate的架構與觀念中,則將更了解物件關聯映射技術的最佳化實踐。
1 則留言:
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
言情小說免費線上閱讀
視訊網
台灣辣妹視訊
視訊網
視訊網
台灣辣妹視訊
xu4的情色小遊戲
ut視訊聊天網
免費視訊
視訊聊天網
視訊網
視訊網
影音視訊聊天室
免費視訊聊天室
台灣辣妹視訊聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
影音視訊聊天
影音視訊聊天
美女主播性感熱舞視頻
美女主播性感熱舞視頻
免費午夜秀視頻聊天室你懂的
免費午夜秀視頻聊天室你懂的
真人美女主播
真人美女主播
台灣辣妹視訊網
台灣辣妹視訊網
台灣辣妹視訊網
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
真愛旅舍視頻聊天室
張貼留言