我在前面一篇文章<Hibernate Annotations 實戰-- 從 hbm.xml 到 Annotations>中,有很多開發者在談論中提到,有沒有必要從 hbm.xml 往 Annotations 上轉移. 那麼在這篇文章中我們就來討論一下 hbm.xml 與 Annotations的優缺點,看看那種情況最適合你.
首先,討論一下 xml 配置文件的優點, 個人認為主要優點就是當你改變底層配置時 不需要改變和重新編譯代碼,只需要在xml 中更改就可以了,例如 Hibernate.cfg.xml 當你要更改底層數據庫時, 只要更改配置文件就可以了.Hibernate會為你做好別的事情.
那麼xml的缺點呢,個人認為有以下幾點:
描述符多,不容易記憶,掌握 要深入了解還有看DTD文件
無法做自動校驗,需要人工查找
讀取和解析xml配置要消耗一定時間,導致應用啟動慢,不便於測試和維護
當系統很大時,大量的xml文件難以管理
運行中保存xml配置需要消耗額外的內存
在O/R Mapping的時候需要在java文件和xml配置文件之間交替,增大了工作量
其中第一 二點 借助於先進的IDE 可能不是什麼問題. 但是對初學者還是個問題
下面我們看看 Annotations的 特性吧! 可以解決xml遇到的問題,有以下優點
描述符減少。以前在xml配置中往往需要描述java屬性的類型,關系等等。而元數據本身就是java語言,從而省略了大量的描述符
編譯期校驗。錯誤的批注在編譯期間就會報錯。
元數據批注在java代碼中,避免了額外的文件維護工作
元數據被編譯成java bytecode,消耗的內存少,讀取也很快,利於測試和維護
關於映射文件是使用 hbm.xml 文件還是使用 Annotations 我們來看看2者的性能吧. 先聲明一下,個人認為映射文件一旦配置好就不會在很大程度上改變了.所以使用xml文件並不會帶來很大的好處.如果你認為 映射文件在你的項目中也經常變化,比如一列String數據 ,今天你使用 length="16" 明天你認為 該數據的長度應該更長才能滿足業務需求 於是改為length="128" 等等類似的問題 . 如果你經常有這方面的變動的話,下面的比較你可以不用看了 , 你應該使用 xml文件 因為Annotations 無法很好的滿足你的要求.
現在讓我們就來看看2者的性能比較吧.
(說明: 這裡只是比較查找 插入 的時間快慢,沒有比較除運行時間以外的其他性能,如 內存占用量 等等)
先來看看測試程序和配置.
首先在 Hibernate.cfg.xml 文件中去掉了
<property name="hibernate.hbm2ddl.auto">update</property>
這一行, 因為在前面的實驗中以及建立了數據庫表了 不再需要更新了.如果你是第一次運行該例子 還是要該行的.
Test.java 如下:
/* * Created on 2005 * @author */ package test.hibernate.annotation; import org.hibernate.Session; import org.hibernate.Transaction; public class Test { public static void main(String [] args) { long start = 0; long end = 0; start = System.currentTimeMillis(); //程序開始時間 Session s = HibernateUtil.currentSession(); long mid = System.currentTimeMillis(); //初始化完畢的時間 (可能此時並沒有初始化完畢^_^) Transaction tx = s.beginTransaction(); /********************測試讀取的代碼************************/ Person p = null; for(int i = 1; i <= 100; i ++) { p = (Person) s.get(Person.class, i); System.out.println(p.getName()); } System.out.println(p.getName()); /********************測試讀取1次的代碼************************/ Person p = null; p = (Person) s.get(Person.class, 1); System.out.println(p.getName()); /*********************測試插入的代碼*************************************/ /* for (int i = 0; i < 100; i ++) { Person p = new Person(); p.setAge(i+1); p.setName("icerain"+i); p.setSex("male"+i); s.save(p); s.flush(); } */ tx.commit(); HibernateUtil.closeSession(); end = System.currentTimeMillis(); //測試結束時間 System.out.println("String[] - start time: " + start); System.out.println("String[] - end time: " + end); System.out.println("Init time : " + (mid-start)); // 打印初始化用的時間 System.out.println("Last time is :" +(end - mid) ); //打印 數據操作的時間 System.out.println("Total time : " +(end - start)); //打印總時間 } }
Annotations 包中的Person.java 如下
package test.hibernate.annotation; import java.util.LinkedList; import java.util.List; import javax.persistence.AccessType; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.GeneratorType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Transient; /** * Person generated by hbm2java */ @SuppressWarnings("serial") @Entity(access = AccessType.PROPERTY) @Table public class Person implements java.io.Serializable { private Integer id; private String name; private String sex; private Integer age; private List list = new LinkedList(); // Constructors /** default constructor */ public Person() { } /** constructor with id */ public Person(Integer id) { this.id = id; } // Property accessors @Id(generate=GeneratorType.AUTO) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Basic public String getName() { return this.name; } public void setName(String name) { this.name = name; } @Basic public String getSex() { return this.sex; } public void setSex(String sex) { this.sex = sex; } @Basic public Integer getAge() { return this.age; } public void setAge(Integer age) { this.age = age; } @Transient public List getList() { return list; } public void setList(List list) { this.list = list; } }
其他的代碼幾乎沒有改變:
下面的每種類型的測試都測試了3次以上, 取中間的測試時間.
測試機器配置:
CPU: AMD Athlon (xp) 2000+
內存: 784880KB
硬盤: 三星 SP0812N
讀取一次 的比較:(單位: 毫秒)
使用Annotations 的測試數據 使用Xml文件的測試數據 簡要說明 Init time : 2444 Init time : 2431 測試前我認為該項結果xml應該比較大,要讀取映射文件啊,實際情況不是這樣,不知道為什麼? Last time is : 62 Last time is : 85 相差比較大不知道為什麼? Total time : 2506 Total time : 2516 xml文件總體上慢了一點讀取100次的比較:
使用Annotations 的測試數據 使用Xml文件的測試數據 簡要說明 Init time : 2437 Init time : 2422 和前面初始化差不多 Last time is : 438 Last time is : 484 有時間差 Total time : 2875 Total time : 2906 也是xml文件總體上慢了一點插入100次的比較:
使用Annotations 的測試數據 使用Xml文件的測試數據 簡要說明 Init time : 2453 Init time : 2469 和前面初始化差不多 Last time is : 469 Last time is : 656 有時間差 Total time : 2922 Total time : 3125 也是xml文件總體上慢了一點從上面的三次對比中大家可以看到 初始化的部分幾乎兩者是一樣的, 在數據操作上面 使用xml文件 總是比使用Annotations 慢一點.在我們只操縱一個只有幾個屬性的小持久化類的操作中就有 幾十毫秒的差距. 幾十毫秒在計算機中算不算很大 大家應該都知道,我就不在多說了.
總結: 經過 xml 文件 和Annotations 的優缺點和 性能上的對比.現在使用那個作為你持久化映射策略.我相信大家都會正確選擇的.