在Object-Relational Database mapping中,hibernate是一個相當受到重視的 函式庫,在即將release的EJB 3.0裡面,persistence的技術會在相當程度中參考hibernate 的設計。這一期我們來看看hibernate的簡單介紹。 hibernate最主要的精神在於將一般的JavaBean和Database進行連結,不同於JDO ( Java Data Object )需要在compile之後對原始的JavaBean進行修改(enhance),hibernate 允許我們直接將一般的JavaBean跟資料庫做連結。在以往的O-R Mapping中,有兩個常見的 作法: 1. 在每個getter/setter函式自行撰寫SQL指令 2. 實作特定的介面,由中繼軟體來呼叫這些介面完成persistence 這兩者都有明顯的缺點,首先,自行撰寫SQL指令就難以避免SQL語法不相容的問題,而且不同Database 對於Transaction和locking的作法不盡相同,使得使用這種作法的程式可攜性很低。第二種作法 往往中繼程式能處理的部份有限,使用者如果要達到足夠的彈性,還是要在實作介面的函式中撰寫 SQL指令。 hibernate比較接近第一種作法,不同的是,在getter/setter中所使用的SQL指令由 hibernate的函式庫在動態產生,由於hibernate的設定檔可以設定對應的SQL語言種類,所以 相容性的問題大大的改善了,在效能上其實難以避免會有一些損失,但是透過reflection和SQL 語法的最佳化,其實效能往往會比 "不小心" 寫得不好的SQL指令要強得多。更令人讚賞的是, hibernate對於資料庫操作的實作相當完整,transaction/large binary/isolation...... 這些比較容易不相容的feature都做了相當夠用的處理。最重要的是,這個函式庫的成熟度相當 高,可以放心的在商業級的專案中使用,這點跟一般opensource的函式庫有相當的不同。 接著我們看一些hibernate相關的設定: 設定檔案分成兩大類:主要設定檔、物件設定檔,前者定義和database相關的設定,後者則用來 定義物件和table的對應。主要設定檔 (hibernate.cfg.xml) 的寫法舉例如下: ============================================================================ org.hsqldb.jdbcDriver jdbc:hsqldb:./defaultdb sa net.sf.hibernate.dialect.HSQLDialect true update ============================================================================= 一開始是一連串有關資料庫連線的設定,請特別注意 "dialect" 這個屬性,這裡我們將SQL指令 的種類設定成依照HyperSonicSQL的語法來動態產生SQL指令,在使用不同的database的時候, 這裡要做對應的修改。 則是指向設定物件的設定檔,如果有多個設定檔, 可以接在後面繼續寫。 接著我們來看物件設定檔的寫法: ============================================================================= ============================================================================= 首先,每各物件都要有id,這有點類似database的primary key,這裡我們使用 讓hibernate自動以遞增的方式來產生id,我們也可以用來自行填入id, 當然,id不能重複,所以筆者會建議採用第一種方式。 id之後就是JavaBean的屬性和table欄位的對應了,後面我們列出這個JavaBean本身,讓大家對照著看看: ============================================================================= public class DataObject { private long key_1=-1; private String id=null; private String name=null; public long getKey_1(){return this.key_1;} public void setKey_1(long key_1){this.key_1=key_1;} public String getId(){return this.id;} public void setId(String id){this.id=id;} public String getName(){return this.name;} public void setName(String name){this.name=name;} } ============================================================================= 編譯之後,不需要做任何額外的處理,只要把需要的函式庫和設定檔擺在classpath裡面,就大功告成了!!