Vincent

          Vicent's blog
          隨筆 - 74, 文章 - 0, 評論 - 5, 引用 - 0

          導航

          <2006年9月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          常用鏈接

          留言簿(5)

          隨筆分類

          隨筆檔案

          我的鏈接

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          Hibernate Annotations 實戰(二)

          -- hbm.xml 與 Annotations 性能比較

          任何獲得Matrix授權的網站,轉載請保留以下作者信息和鏈接:
          作者:icess(作者的blog:http://blog.matrix.org.cn/page/icess)
          關鍵字:Hibernate Validator

          我在前面一篇文章<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 : 2444Init time : 2431測試前我認為該項結果xml應該比較大,要讀取映射文件啊,實際情況不是這樣,不知道為什么?
          Last time is :62Last time is :85相差比較大不知道為什么?
          Total time : 2506Total time : 2516xml文件總體上慢了一點

          ?? 讀取100次的比較:

          使用Annotations 的測試數據使用Xml文件的測試數據簡要說明
          Init time : 2437Init time : 2422和前面初始化差不多
          Last time is :438Last time is :484有時間差
          Total time : 2875Total time : 2906也是xml文件總體上慢了一點

          插入100次的比較:

          使用Annotations 的測試數據使用Xml文件的測試數據簡要說明
          Init time : 2453Init time : 2469和前面初始化差不多
          Last time is :469Last time is :656有時間差
          Total time : 2922Total time : 3125也是xml文件總體上慢了一點

          從上面的三次對比中大家可以看到 初始化的部分幾乎兩者是一樣的, 在數據操作上面 使用xml文件 總是比使用Annotations 慢一點.在我們只操縱一個只有幾個屬性的小持久化類的操作中就有 幾十毫秒的差距. 幾十毫秒在計算機中算不算很大 大家應該都知道,我就不在多說了.

          總結: 經過 xml 文件 和Annotations 的優缺點和 性能上的對比.現在使用那個作為你持久化映射策略.我相信大家都會正確選擇的.

          測試后記: 經過多次測試 感覺有時候很不穩定 ,有的時候很穩定不知道是測試有問題還是別的問題.大家可以自己測試一下. 有什么新的發現 請大家討論討論.

          posted on 2006-09-01 14:04 Binary 閱讀(345) 評論(0)  編輯  收藏 所屬分類: Hibernate

          主站蜘蛛池模板: 高密市| 大田县| 清徐县| 遂平县| 绥中县| 乌拉特中旗| 江门市| 苍梧县| 高唐县| 阿拉善左旗| 东城区| 项城市| 白朗县| 齐齐哈尔市| 自贡市| 理塘县| 伊金霍洛旗| 惠东县| 邢台市| 寿宁县| 瑞安市| 望都县| 秦皇岛市| 芒康县| 潮安县| 彰武县| 错那县| 汶上县| 滦平县| 郎溪县| 卫辉市| 高雄县| 织金县| 望江县| 咸阳市| 怀远县| 台山市| 晋宁县| 固阳县| 吴堡县| 巴马|