<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    空間站

    北極心空

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

    一. ????????????

    在實際項目中使用Hibernate有兩年多了,在兩年多的實踐過程中既體驗到了Hibernate帶來的N多好處,同時也碰到不少的問題,特寫此篇文章做個總結(jié),記錄自己在Hibernate實踐中的一些經(jīng)驗,希望對于新使用Hibernate的朋友能有個幫助,避免走過多的彎路。

    閱讀本文前建議至少擁有Hibernate的一些基本知識,因為本文不會去詳細介紹相關(guān)的基本知識,最好就是先用Hibernate開發(fā)了一個HelloWorld,^_^

    根據(jù)自己所經(jīng)歷的項目中使用Hibernate所涉及的范圍,本文從開發(fā)環(huán)境、開發(fā)、設(shè)計、性能、測試以及推薦的相關(guān)書籍方面進行講述,本篇文檔不會講的非常細致,只是根據(jù)自己在實踐時的經(jīng)驗提出一些建議,關(guān)于細致以及具體的部分請參閱《Hibernate Reference》或推薦的相關(guān)書籍章節(jié)。

    此文檔的PDF版本請到此下載:

    http://www.tkk7.com/Files/BlueDavy/Hibernate 實踐.rar

    本文允許轉(zhuǎn)載,但轉(zhuǎn)載時請注明作者以及來源。

    作者:BlueDavy

    來源:www.tkk7.com/BlueDavy

    二. ???????????? 開發(fā)環(huán)境

    Hibernate 開發(fā)環(huán)境的搭建非常的簡單,不過為了提高基于Hibernate開發(fā)的效率,通常都需要使用一些輔助工具,如xdoclet、middlegen等。

    盡管Hibernate已經(jīng)封裝提供了很簡單的進行持久的方法,但在實際項目的使用中基本還是要提供一些通用的代碼,以便在進行持久的相關(guān)操作的時候能夠更加的方便。

    2.1. lib

    2.1.1. ?????? Hibernate lib

    Hibernate 相關(guān)的 lib 自然是開發(fā)環(huán)境中首要的問題,這部分可以從 Hibernate 的官方網(wǎng)站進行下載,在其官方網(wǎng)站中同時提供了對于 Hibernate 所必須依賴的 lib 以及其他可選 lib 的介紹。

    2.2. xdoclet

    Hibernate 作為ORM工具,從名字上就能看出它需要一個從O à R Mapping的描述,而這個描述就是在使用Hibernate時常見的hbm.xml,在沒有工具支持的情況下,需要在編寫持久層對象的同時手寫這個文件,甚為不便。

    jdk 5.0未推出之前,xdoclet支持的在javadoc中編寫注釋生成相關(guān)配置文件的方式大受歡迎,減少了編寫hibernate映射文件的復雜性,手寫一個完整的hibernate映射文件出錯幾率比較的高,再加上手寫容易造成編寫出來的風格相差很大,因此,基于xdoclet來生成hbm.xml的方式被大量的采用,基于xdoclet來編寫能夠基于我們在持久層對象上編寫的javadoc來生成hbm.xml文件,非常的方便。

    2.2.1. ?????? Hibernate template

    如果沒記錯的話,大概在 04 年的時候 javaeye 上有位同仁整理了一個這樣的 template 文件, ^_^ ,非常感謝,我一直都在用著,呵呵。

    這個文件的方便就是把它導入 eclipse 后,在 javadoc 中我們可以直接寫 hibid ,然后按 eclipse 的代碼輔助鍵 (alt+/) 來生成整個 hibernate.id 的相關(guān)的格式,呵呵,免得在寫 hibernate.id 這些東西的時候過于麻煩, ^_^ ,這個 template 文件我稍微做了修改,可在這里下載:

    http://www.tkk7.com/Files/BlueDavy/templates-eclipse-tags.rar

    當然,你也可以選擇直接用 xdoclet 提供的 template 文件,不過 xdoclet 官方網(wǎng)站上好像只提供了可直接導入 idea 的模板文件。

    關(guān)于注釋上的 hibernate.id 這些東西具體請參見 xdoclet 官方網(wǎng)站的說明。

    如果你的項目采用的是 jdk 5 ,那么就可以直接使用 hibernate annotation 了,那就更為方便。

    2.2.2. ?????? Ant task build

    Eclipse 里沒有集成 xdoclet 的插件,你也可以去安裝一個 jboss ide 的插件,里面有 xdoclet 的插件,反正我是覺得太麻煩了。

    在項目中我仍然采用 ant task 的方式來生成 hbm.xml , target 如下所示:

    <path id="app.classpath">

    <pathelement path="${java.class.path}"/>

    <fileset dir="${xdoclib.dir}">

    <include name="*.jar"/>

    </fileset>

    </path>

    <target name="hbm" description=" 生成映射文件 ">

    <tstamp>

    <format property="TODAY" pattern="yy-MM-dd"/>

    </tstamp>

    <taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask" classpathref="app.classpath"/>

    <hibernatedoclet destdir="src/java" force="true" verbose="true" excludedtags="@version,@author,@todo">

    <fileset dir="src/java"> ?

    <include name="**/po/**/*.java"/>

    </fileset>

    <hibernate version ="3.0"/>

    </hibernatedoclet>

    </target>

    這個文件請根據(jù)項目情況以及環(huán)境稍做修改, ^_^ ,其中需要通過 properties 文件指明 xdocletlib.dir ,類似 xdocletlib.dir=c:\xdocletlib ,里面放置 xdoclet 的相關(guān) jar 文件。

    在搭建好了這樣的環(huán)境后,就可以在直接在 eclipse 中運行 ant 文件中的這個 target 來生成 hbm.xml

    2.3. Hibernate3 Tools

    如果采用Hibernate 3,則可以直接下載Hibernate 3 ToolsEclipse Plugin,那就可以類似在PL/SQL里執(zhí)行sql一樣在eclipse里執(zhí)行hql,^_^

    2.4. HibernateUtil

    為了方便項目中Hibernate的使用,一般來說都會提供HibernateUtil這樣的類,這個類的作用主要是創(chuàng)建sessionFactory和管理session,在Hibernate 3以前采用的是在這里建立ThreadLocal來存放session,在Hibernate 3以后則可以直接使用SessionFactory.getCurrentSession來獲取session,而session的獲取方式則可通過在hibernate.cfg.xml中執(zhí)行current_session_context_class的屬性來決定是采用threadjta或自定義的方式來產(chǎn)生session。

    2.5. CommonDao

    在持久層部分目前采用的較多的仍然是dao模式,Hibernate作為ORM工具已經(jīng)提供了CRUD的封裝,類如可以使用session.save()session.persist()這樣簡單的方式來完成CRUD的操作,但在實際的項目中還是需要提供一個通用的Dao,來簡化對于事務(wù)、異常處理以及session的操作,同時提供一些項目中需要的相關(guān)操作。

    三. ???????????? 開發(fā)

    在完成了Hibernate的開發(fā)環(huán)境的搭建后,就可以基于Hibernate進行持久層的開發(fā)了,對于持久層開發(fā)來說,會涉及到實體的編寫、實體的維護以及實體的查詢?nèi)齻€部分。

    3.1. 實體的編寫

    Hibernate 的一個明顯的優(yōu)點就是在于可透明化的對對象進行持久,這也就意味著持久對象根本就不需要依賴任何的東西,可以采用POJO的方式來編寫,在Hibernate 3以上版本還提供了對于MapXML的方式的持久的支持,就更方便了,在項目中,更多采用的仍然是POJO的方式。

    在實體的編寫上應該說不會有什么問題,只要仔細查看xdoclet關(guān)于hibernatedoclet部分的說明即可完成。

    這塊需要學習的主要是普通的值類型注釋的編寫、id字段注釋的編寫、關(guān)聯(lián)注釋的編寫,這些部分xdoclet均提供了較詳細的說明。

    3.2. 實體的維護

    3.2.1. ?????? 新增 / 編輯 / 刪除

    新增 / 編輯 / 刪除是持久操作中最常使用的維護性操作,基于 Hibernate 做這樣的維護就比采用 sql 的方式簡單多了,通過上面 CommonDao ,就可以直接完成 dao.save dao.update 、 dao.delete 的操作,而且在 Hibernate 3 也支持了批量的 insert 、 update delete

    這個部分中需要注意的是 Hibernate 對于對象的三種狀態(tài)的定義:

    u?????? Transient

    很容易理解,就是從未與 session 發(fā)生過關(guān)系的對象, ^_^ ,例如在代碼中直接 User user=new User() ;這樣形成的 user 對象,就稱為 Transient 對象了。

    u?????? Detached

    同樣很容易理解,就是與 session 發(fā)生過關(guān)系的對象,但 session 已經(jīng)關(guān)閉了的情況下存在的對象,例如:

    User user=new User();

    user.setName(“bluedavy”);

    session.save(user);

    session.close();

    session.close() 后這個時候的 user 對象就處于 Detached 狀態(tài)之中了,如果想將這個對象變?yōu)?/span> Persistent 狀態(tài),可以通過 session.merge session.saveOrUpdate() 等方式來實現(xiàn)。

    Detached 狀態(tài)的對象在實際的應用中最常采用,從概念上我們可以這么理解,處于 Detached 狀態(tài)的對象可以看做是一個 DTO ,而不是 PO ,這從很大程度上就方便了 PO 在實際項目中的使用了。

    u?????? Persistent

    Persistent 狀態(tài)就是指和 Session 發(fā)生了關(guān)系的對象,并且此時 session 未關(guān)閉,舉例如下:

    User user=new User();

    user.setName(“bluedavy”);

    session.save(user);

    user.getName();

    session.save user 就處于 Persistent 狀態(tài),此時如果通過 session 根據(jù) user id 去獲取 user 對象,則可發(fā)現(xiàn)獲取的對象和之前的 user 是同一個對象,這是 session 一級緩存所起的作用了,當然,也可以強制的刷新 session 的一級緩存,讓 session 從數(shù)據(jù)庫中重新獲取,只需要在獲取前執(zhí)行 session.evict(user) session.clear() 。

    3.2.2. ?????? 關(guān)聯(lián)維護

    關(guān)聯(lián)維護在 Hibernate 中表現(xiàn)出來可能會讓熟悉使用 sql 的人有些的不熟,但其實以對象的觀點去看是會覺得很正常的。

    Hibernate 的關(guān)聯(lián)維護中,最重要的是 inverse cascade 兩個概念。

    u?????? inverse

    inverse 從詞義上看過去可能不是那么容易理解,其實它的意思就是由誰來控制關(guān)聯(lián)關(guān)系的自動維護,當 inverse=true 就意味著當前對象是不能自動維護關(guān)聯(lián)關(guān)系,當 inverse=false 就意味著當前對象可自動維護關(guān)聯(lián)關(guān)系,還是舉例來說:

    假設(shè) Org User 一對多關(guān)聯(lián),

    org getUsers inverse=false 的情況:

    org.getUsers().add(user);

    dao.save(org);

    這樣執(zhí)行后將會看到數(shù)據(jù)庫中 user 這條記錄中的 orgId 已經(jīng)被設(shè)置上去了。

    inverse=true 的情況下,執(zhí)行上面的代碼,會發(fā)現(xiàn)在數(shù)據(jù)庫中 user 這條記錄中的 orgId 沒有被設(shè)置上去。

    ^_^ , inverse 的作用這樣可能看的不是很明顯,在下面的一對多中會加以描述。

    u?????? cascade

    cascade 的概念和數(shù)據(jù)庫的 cascade 概念是基本一致的, cascade 的意思形象的來說就是當當前對象執(zhí)行某操作的情況下,其關(guān)聯(lián)的對象也執(zhí)行 cascade 設(shè)置的同樣的操作。

    例如當 org.getUsers cascade 設(shè)置為 delete 時,當刪除 org 時,相應的 users 也同樣被刪除了,但這個時候要注意, org.getUsers 這個集合是被刪除的 user 的集合,也就是說如果這個時候數(shù)據(jù)庫中新增加了一個 user org ,那么這個 user 是不會被刪除的。

    cascade 的屬性值詳細見《 Hibernate reference 》。

    3.2.2.1. ????????? 一對一

    一對一的關(guān)聯(lián)維護在實際項目中使用不多,一對一在Hibernate中可采用兩種方式來構(gòu)成,一種是主鍵關(guān)聯(lián),一種是外鍵關(guān)聯(lián)。

    一對一的使用推薦使用主鍵關(guān)聯(lián),具體配置方法請參見《Hibernate Reference》。

    3.2.2.2. ????????? 一對多/多對一

    一對多/多對一的關(guān)聯(lián)維護在實際項目中使用是比較多的,在Hibernate中可采用多種方式來配置一對多的關(guān)聯(lián),如采用Set、List、BagMap等,具體在《Hibernate Reference》中都有詳細說明。

    在這里我想說的一點就是關(guān)于inverse的設(shè)置,在一對多的情況下建議將一端的inverse設(shè)為true,而由多端去自動維護關(guān)聯(lián)關(guān)系,為什么這樣做其實挺容易理解的,假設(shè)orguser為一對多的關(guān)聯(lián),org.getUsersinverse設(shè)置為falseorg.getUsers().add(user);dao.update(org);update的時候org所關(guān)聯(lián)的所有userorgId都會更新一次,可想而知這個效率,而如果改為在多端維護(多端設(shè)置為inverse=false),則是這樣:user.setOrg(org);dao.update(user);update的時候就僅僅是更新user這一條記錄而已。

    另外一點就是合理的設(shè)置cascade,這個要根據(jù)需求來實際決定。

    3.2.2.3. ????????? 多對多

    多對多的關(guān)聯(lián)維護在實際項目中其實也是比較多的,盡管在《Hibernate Reference》中認為多對多的情況其實很多時候都是設(shè)計造成的。

    多對多的關(guān)聯(lián)也同樣可以采用Set、List等多種方式來配置,具體在《Hibernate Reference》中也有詳細的說明。

    多對多的關(guān)聯(lián)維護上沒有什么需要多說的,在實踐過程中來看這塊不會出什么太多問題,唯一需要注意的是合理設(shè)置cascade,這個要根據(jù)項目的實際情況而定。

    3.3. 實體的查詢

    Hibernate 提供了多種方式來支持實體的查詢,如對于原有熟悉sql的人可以繼續(xù)使用sql,符合對象語言的對象查詢語句(HQL)以及條件查詢API(Criteria)。

    在熟練使用hqlcriteria的情況下,我相信你會覺得Hibernate的查詢方式會比采用sql的方式更加簡便。

    3.3.1. ?????? 符合對象語言的查詢語句

    Hibernate 提供了一種符合對象語言的查詢語句,稱為 HQL ,這種語句的好處是能夠避免使用 sql 的情況下依賴數(shù)據(jù)庫特征的情況出現(xiàn),同時它帶來的最大的好處就是我們能夠根據(jù) OO 的習慣去進行實體的查詢。

    對于 HQL 沒有什么多講的,如果熟悉 sql 的人應該也是能夠很快就學會 HQL ,而如果不熟悉 sql 的人那也沒關(guān)系, HQL 的上手是非常容易的,具體請參考《 Hibernate Reference 》。

    3.3.2. ?????? 占位符式的查詢

    占位符式的查詢 ( 就是采用 ? 替換查詢語句中的變量 ) 是在采用 sql 的情況下經(jīng)常使用的一種查詢方式,也是查詢時推薦使用的一種方式。

    Hibernate 中的查詢參數(shù)主要有兩種類型:值類型和實體類型,值類型就是指一個切實的值 ( String 、 int 、 List 這些 ) ,實體類型就是一個具體的實體,如編寫的 User 、 Organization 等,值類型的查詢和普通 sql 幾乎一樣,而實體類型的查詢就體現(xiàn)了 Hibernate 的強項, ^_^ ,可以起到簡化 sql 的作用,并且使得查詢語句更加容易理解。

    3.3.2.1. ????????? 值類型

    3.3.2.1.1.????? 簡單值

    舉例如下:

    from User u where u.name=:username and u.yearold=:yearold

    這就是一個常見的簡單值的占位符式的查詢,通過這樣的方式就可以把值注入到參數(shù)中:

    query.setParameter(“username”,”bluedavy”);

    query.setParameter(“yearold”,25);

    同樣, hibernate 也支持和 sql 完全相同的 ? 的方式,那么上面的語句以及注入?yún)?shù)的方式就變?yōu)榱耍?/span>

    from User u where u.name=? and u.yearold=?

    query.setParameter(0,”bluedavy”);

    query.setParameter(1,25);

    推薦使用第一種,那樣參數(shù)的意義更容易被理解。

    3.3.2.1.2.????? in 查詢

    in 查詢也是經(jīng)常被使用到的一種查詢,在 Hibernate 中表現(xiàn)出來會稍有不同,不過如果按照對象觀點去看就很容易理解了,例如下面這句:

    from User u where u.name in (:usernameList)

    Hibernate 中通過這樣的方式將值注入到這個參數(shù)中:

    List list=new ArrayList();

    list.add(“jerry”);

    list.add(“bluedavy”);

    query.setParameterList(“usernameList”,list);

    sql 中通常是組裝一個由 , 連接的值來構(gòu)成 in 中的參數(shù)值,而在 Hibernate 中則依照對象轉(zhuǎn)化為采用 list 了, ^_^ ,是不是更方便些。

    3.3.2.2. ????????? 實體類型

    Hibernate中關(guān)聯(lián)采用的都是對象形式,表現(xiàn)對外就是隱藏了數(shù)據(jù)庫的外鍵的部分,這也就對習慣使用sql查詢的人帶來一個問題,因為無法再操作外鍵字段,那么在涉及到關(guān)聯(lián)的實體的查詢時應該怎么做呢,我把它分為單實體和實體集合兩種情況來說說。

    3.3.2.2.1.????? 單實體

    單實體的查詢對應到 sql 情況通常是在一對多的情況下通過多端查詢同時結(jié)合一端的一些過濾條件,在 sql 中通常采用 join 的方式來實現(xiàn)這個,而在 Hibernate 中要實現(xiàn)這點就更容易了,舉例如下:

    User Organization 是一對多,現(xiàn)在要查詢屬于組織機構(gòu)名稱為 ”Blogjava” 以及用戶年齡大于 20 的用戶:

    from User u where u.org.name=:orgname and u.yearold>:yearold

    query.setParameter(“orgname”,”Blogjava”);

    query.setParameter(“yearold”,20);

    可以看到這樣的查詢語句比 sql 更簡單多了,同時也更容易理解多了。

    3.3.2.2.2.????? 實體集合

    實體集合過濾形式的查詢在實際的項目中也經(jīng)常會碰到,仍然用上面的例子,但改為通過 Organization 去查詢:

    from Organization org where org.name=:orgname and org.users.yearold>:yearold

    是不是比 sql 簡單多了,而且更容易理解呢, ^_^

    這個時候?qū)ο蠡樵冋Z句的優(yōu)勢就體現(xiàn)出來了,而不用陷入 sql 的那種關(guān)系型的通過外鍵進行查詢的方式。

    3.3.3. ?????? NamedQuery

    NamedQuery 的意思就是指在 PO 的映射文件中定義關(guān)于 PO 的查詢語句,而在應用中指需要直接調(diào)用此查詢語句的別名即可,這個好處非常明顯,使得所有的查詢語句可以統(tǒng)一的進行管理,同樣,我們可以在 PO 中通過 javadoc 的方式進行定義,這就更方便了, ^_^

    操作 NamedQuery 的方法和普通 hql 的方法基本一樣:

    session.getNamedQuery(queryname);

    其中的 queryname 就是我們定義的查詢語句的別名,一個 namedQuery 的語句的示例如下:

    < query name = "validate" ><![CDATA[

    from User u where u.loginname=:loginname and u.password=:password

    ]]></ query >

    3.3.4. ?????? Criteria

    條件查詢的 API 使得我們可以采用完全對象化的方式進行實體的查詢,而不是通過 hql 的方式,在實際項目中,使用 hql 的方式更為居多,畢竟寫起來更方便。

    關(guān)于 Criteria 的具體介紹請參閱《 Hibernate Reference 》。

    3.3.5. ?????? 原生 SQL

    原生 SQL 不推薦使用,但在某些確實需要用 sql 的情況下那么 Hibernate 還是支持的,具體見《 Hibernate Reference 》。

    四. ???????????? 設(shè)計

    獨立的編寫這個章節(jié)的原因是希望在采用Hibernate的情況下充分的去發(fā)揮Hibernate的優(yōu)勢,改變我們以關(guān)系形式去做持久層的設(shè)計的慣性思維,形成以OO的思想去設(shè)計持久層,所以我非常推薦通過寫PO去生成數(shù)據(jù)表的方式,而不是設(shè)計表反向?qū)С?span lang="EN-US">PO的形式,當然,對于原有的系統(tǒng)那就沒辦法了。

    OO 思想中的核心三要素:封裝、繼承和多態(tài),在Hibernate的支持下同樣可以充分發(fā)揮OO的三要素來優(yōu)化持久層的設(shè)計。

    4.1. 封裝

    4.1.1. ?????? Component

    Hibernate 中有一個 Component 的概念,這就允許在進行持久層設(shè)計的時候采用細粒度級的領(lǐng)域模型進行設(shè)計,例如在 User 對象中需要記錄 User firstname lastname 這些信息,而在其他的表中也有這種需求,那么在 Hibernate 中我們就可以把 firstname 、 lastname 組裝為一個 UserName 對象,作為 Component 放入 User 中,在 user 中就可以變?yōu)椴捎?/span> user.getUserName.getFristName 的方式來獲取。

    Component 對于我們采用對象的封裝概念進行持久層設(shè)計提供了很好的支持,同時在 Hibernate 中還有 Elements 、 Properties 這些元素,具體請參見《 Hibernate Reference 》。

    4.2. 繼承

    繼承使得我們可以對持久層中的對象進行抽象,類如我們可以形成Person這個對象,而User、Employee都繼承自這個對象。

    繼承在數(shù)據(jù)庫形式的設(shè)計中固然也可以實現(xiàn),但通常不能以對象的觀點去發(fā)揮的淋漓盡致,當然不是說以對象的方式去設(shè)計一定是最好的。

    Hibernate中對于繼承映射到數(shù)據(jù)表有幾種不同的策略,各有適用的不同場合,具體的解釋和說明見《Hibernate Reference

    4.2.1. ?????? 單表策略

    單表策略很容易理解,就是將類、子類中所有的屬性都放至一張表中,這對于子類屬性不多的情況非常有效。

    Hibernate 中通常將子類定義為 @hibernate.subclass 的方式來實現(xiàn)這個策略。

    4.2.2. ?????? 每個子類一張表

    每個子類一張表在 Hibernate 中有幾種實現(xiàn)方式, @hibernate.join-subclass 、 @hibernate.join-subclass-key 的組合方式以及 @hibernate.join-subclass 、 @hibernate.discriminator 的組合方式是較常用的兩種方式,第一種方式采用的是主鍵關(guān)聯(lián)方式,第二種方式采用的是 discriminator 字段的關(guān)聯(lián)方式,個人比較推崇第一種方式。

    這種策略適合在子類屬性和父類有較大不同的情況下采用。

    4.2.3. ?????? 每個具體類一張表

    這種策略適合在類層次結(jié)構(gòu)上有一定數(shù)量的抽象類的情況下使用,同樣有兩種方式,一種是采用顯式多態(tài)的方式,另一種是采用隱式多態(tài)的方式,顯式多態(tài)采用的為 @hibernate.union-subclass 的方式,隱式多態(tài)則采用每個具體類的 PO 獨立建表的策略,在它的映射文件中將看不出任何的和接口、抽象類的關(guān)系,同時對于抽象類,需要指明其 abstract=”true”

    4.3. 多態(tài)

    4.3.1. ?????? 查詢

    在查詢中很容易體現(xiàn) Hibernate 對于多態(tài)的支持,如系統(tǒng)有 Person 對象、 User Employee 分別繼承自 Person ,同時 Person Organization 對象關(guān)聯(lián),這個時候我們通過 Organization 獲取其關(guān)聯(lián)的 Person 時得到的既有可能是 User ,也有可能是 Employee ^_^…

    五. ???????????? 性能

    Hibernate 作為ORM工具,從性能上來講帶給了很多人憂慮,但我覺得Hibernate在性能上也許會帶來少許的降低,但如果對于不能合理設(shè)計數(shù)據(jù)庫和使用SQL的人來說,我覺得Hibernate反倒能提高性能,除非是在一些特殊的場合,如報表式的那種查詢推薦繼續(xù)采用JDBC的方式。

    Hibernate 在性能提升上其實有很多種做法,在《Hibernate Reference》中也有專門的提升性能的章節(jié),在這里我提幾點在項目中通常采用的方法。

    5.1. Lazy Load

    Lazy Load 是常用的一種提升性能的方法,這個其實很容易理解,在不采用lazy load的情況下,Hibernate在獲取一個PO的時候,將同時獲取PO中的屬性、PO中的集合以及集合中對象的屬性、集合,這樣看過去很容易看出,如果對象的關(guān)聯(lián)結(jié)構(gòu)有深層次的話,最后搞不好整個庫都被加載出來了,而在實際使用中往往可能只需要用到PO中的一兩個屬性而已,這點也是之前的ORM產(chǎn)品經(jīng)常被批的一點,就是ORM產(chǎn)品不能象sql那樣只獲取需要的東西,^_^,其實Hibernate在這點上一直就支持,而且支持的還不錯,在Hibernate 3以后,默認的lazy就已經(jīng)設(shè)置為true了,這個時候包括po中的屬性都是采用lazy load的方式,只有在調(diào)用到這個屬性時才會從緩存或數(shù)據(jù)庫中加載,當然,集合也同樣如此。

    lazy load上推薦不要什么字段都采用lazy load的方式,對于一些基本屬性的字段建議將其lazy設(shè)置為false,而對于一些可能需要消耗內(nèi)存的字段,如clob這樣的字段對象的lazy設(shè)置為true,對于集合則全部設(shè)置為lazy=true。

    是否采用Lazy load對系統(tǒng)的性能會有非常明顯的影響,同時盡量不要將Detached Object放入Httpsession中。

    5.1.1. ?????? OSIV

    OSIV Open Session In View ,在 B/S 系統(tǒng)中通常采用這種方式來更好的去支持 Lazy load ,意思就是在 View 加載前打開 Session ,在 View 加載完畢后關(guān)閉 Session 的方式,在 Spring 中有 OpenSessionInViewFilter ,可參考或直接使用。

    5.2. Cache

    Cache 是在提升系統(tǒng)性能方面常用的方法,在Hibernate中通常有非常好的對于Cache的支持方法,Hibernate中對于Cache有一級緩存和二級緩存的概念,一級緩存是必須的,位于Session部分,二級緩存則不是必須的,由開發(fā)人員自行指定,二級緩存可指定使用何種開源的cache工具,Hibernate 3以后的版本默認使用的是Ehcache,也可以切換為OscacheJbossCache,對我而言最重要的區(qū)別在于對于cluster的支持上。

    二級緩存能夠明顯的提高系統(tǒng)的性能,當然,同時也會更加的消耗內(nèi)存,可以通過配置文件來指定內(nèi)存中能夠加載的最多的元素,這有利于避免消耗過多內(nèi)存。

    二級緩存的設(shè)置在Hibernate中非常的簡單,只需要在相應的hbm.xml中增加cache元素,指明使用何種策略,如read-only、read-write等,也可以直接在hibernate.cfg.xml中增加class-cache的方式來進行全局指定。

    5.3. 高效的查詢語句

    查詢語句的是否高效對于系統(tǒng)的性能也是會造成明顯的影響的,為了方便系統(tǒng)性能的調(diào)優(yōu),建議大家對查詢語句進行統(tǒng)一管理,如統(tǒng)一采用NamedQuery的方式,在這樣的情況下可以在系統(tǒng)運行時請教數(shù)據(jù)庫專家,由他們來分析系統(tǒng)中的查詢語句的執(zhí)行效率以及提出改進策略,而對于開發(fā)人員來講,在查詢語句方面最能夠注意的就是采用占位符式的查詢。

    5.3.1. ?????? 占位符式的查詢

    數(shù)據(jù)庫對于所有的 sql 語 句都要進行語法分析,而其分析通常會受到語句中的大小寫、空格以及參數(shù)不同的影響,在其語法分析器認為不同的情況下將再次進行分析,這就不可避免的降低了 響應的速度,而采用占位符式的查詢則可保證語法分析器只進行一次的分析,在參數(shù)不同的情況并不會出現(xiàn)重復解析的現(xiàn)象,其次就是要統(tǒng)一查詢語句的編寫風格, 包括大小寫、空格這些。

    我不是很確定 Hibernate 中對于語句的語法分析,估計和數(shù)據(jù)庫的這種方式應該差不多,不過猜想可能會更智能一些, ^_^

    5.4. 一些配置

    hibernate.cfg.xml 中的一些配置也會對性能產(chǎn)生一定的影響,如 jdbc.fetch_size 的設(shè)置等,還有象采用連接池方面的設(shè)置,對于 B/S 應用的情況建議盡量采用應用服務(wù)器提供的 JNDI 的方式。

    5.5. 建議

    在性能提升方面從兩方面入手,一是持久層對象的設(shè)計上,這方面可以參考《 Hibernate Reference 》中提升性能章節(jié)中的一些建議,另一方面則是請教數(shù)據(jù)庫專家,由數(shù)據(jù)庫專家對表結(jié)構(gòu)、查詢語句等進行分析來給出改進策略,在現(xiàn)有的一個項目中,竟然有出現(xiàn) Hibernate 在外鍵上沒建立索引的現(xiàn)象出現(xiàn)?

    六. ???????????? 測試

    6.1. 編寫專門的測試用的配置文件

    測試方面也是極度關(guān)心的話題,在測試方面其實比較簡單,只需要在測試類中采用專門用于測試的配置文件即可,在這個配置文件中,通過都是采用設(shè)置hbm2ddl.auto屬性為create-drop的方式,也就是在測試類運行前創(chuàng)建表,在測試類運行后刪除表的策略,在更多的情況下,我們可以采用in-memory的數(shù)據(jù)庫的方式,如hsql,當然,有些時候則需要和實際運行環(huán)境一致,那么就需要采用建立專門的測試庫的方式,避免測試數(shù)據(jù)和運行數(shù)據(jù)的相互影響。

    七. ???????????? 企業(yè)應用開發(fā)

    事務(wù)和并發(fā)是企業(yè)應用開發(fā)中非常關(guān)注的兩個話題,在《Hibernate Reference》中提供了詳細的方案,在這里我就簡單的說說。

    7.1. 事務(wù)

    事務(wù)是企業(yè)應用開發(fā)中非常重視的一點,而在Hibernate中操作此部分和sql方式?jīng)]有什么很大的區(qū)別,可以通過session主動去獲取Transaction來實現(xiàn)事務(wù)控制,同時也可以交由應用服務(wù)器提供的JTA來實現(xiàn)事務(wù)控制。

    在事務(wù)這個級別上如果有更高的要求,建議采用Spring的事務(wù)框架。

    7.2. 并發(fā)

    在并發(fā)方面多采用鎖策略,鎖策略和數(shù)據(jù)庫基本相同,同樣是樂觀鎖和悲觀鎖兩種策略,樂觀鎖策略在Hibernate中推薦使用versiontimestamp來實現(xiàn),具體覆蓋方式則需要根據(jù)應用而定,如是采用最新的修改的覆蓋還是采用版本沖突策略等,悲觀鎖策略則通過指定對象的鎖方式,如LockMode.READ,引用《Hibernate Reference》中的一段話:

    “用戶其實并不需要花很多精力去擔心鎖定策略的問題。通常情況下,只要為JDBC連接指定一下隔離級別,然后讓數(shù)據(jù)庫去搞定一切就夠了。然而,高級用戶有時候希望進行一個排它的悲觀鎖定,或者在一個新的事務(wù)啟動的時候,重新進行鎖定。Hibernate總是使用數(shù)據(jù)庫的鎖定機制,從不在內(nèi)存中鎖定對象!

    如果數(shù)據(jù)庫不支持用戶設(shè)置的鎖定模式,Hibernate將使用適當?shù)奶娲J?,這一點可以確保應用程序的可移植性?!薄?span lang="EN-US">

    用戶可通過幾種方式來指定鎖定模式:

    u?????? Session.load() 的時候指定鎖定模式LockMode;

    u?????? Session.lock() ;

    u?????? Query.setLockMode() 。

    八. ???????????? 相關(guān)書籍

    Hibernate 上手并不難,但要真正的用好它確實不是件容易的事,有些書籍能夠很好的幫我們快速的提供解決思路和解決方案,而這些書籍我們也應該常備,以方便自己在有些問題上的解答。

    同時,我一直堅持的觀點,一種開源框架通常帶來的不僅僅是開發(fā)、使用上的改變,帶來的最大的改變?nèi)匀皇窃谠O(shè)計層次上的,設(shè)計上能否充分的發(fā)揮開源框架的優(yōu)勢才是最為重要的。

    8.1. Hibernate Reference

    這本沒什么說的,必讀書籍,也許在讀的時候很多東西你不會覺得什么,但當碰到一些確定方向的問題時,可以通過此書快速的查找到相應的解決方案,感謝Redsaga組織的翻譯工作,使得我們可以有中文版可看。

    目前版本(Hibernate 3.1.2)的下載地址:

    http://www.redsaga.com/hibernate-ref/3.1.2/zh-cn/pdf/hibernate_reference.pdf

    8.2. Hibernate in action

    In action 系列的書籍也沒啥多說的,強烈推薦看看,盡管現(xiàn)在看起來版本有些老了,但里面很多的實踐思想仍然是非常值得學習的,網(wǎng)上應該有很多電子版下載的地方。

    8.3. 《深入淺出Hibernate

    這本書想必大家也聽聞了不少,簡稱白皮書,^_^,是夏昕、曹曉剛以及唐勇三位大師的大作。

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=656038

    posted on 2006-12-22 14:40 蘆葦 閱讀(442) 評論(0)  編輯  收藏 所屬分類: Hibernate
    主站蜘蛛池模板: 亚洲综合伊人制服丝袜美腿| 亚洲精品无码永久在线观看男男| 亚洲色偷偷偷综合网| 一级一片免费视频播放| 国产成人精品免费午夜app | 亚洲网站在线播放| 免费观看四虎精品成人| 97视频免费观看2区| 国产一区二区三区无码免费| 亚洲精品高清视频| 成年免费大片黄在线观看com| a拍拍男女免费看全片| 亚洲另类少妇17p| 亚洲av无码专区在线| 国产猛男猛女超爽免费视频| 国产精品成人无码免费| 久久久久久久亚洲Av无码| 男女男精品网站免费观看| 久久99九九国产免费看小说| 亚洲日韩欧洲无码av夜夜摸 | 亚洲一卡二卡三卡四卡无卡麻豆| 一级免费黄色大片| 成年女人喷潮毛片免费播放| 亚洲高清国产AV拍精品青青草原 | 99久热只有精品视频免费观看17| 国产免费啪嗒啪嗒视频看看 | 亚洲国产精品成人精品软件| 国产精品免费观看视频| 四虎影院免费在线播放| 1区1区3区4区产品亚洲| 国产伦精品一区二区免费| 永久中文字幕免费视频网站| 亚洲精品一卡2卡3卡三卡四卡| 国产高潮久久免费观看| 国产一级淫片视频免费看| 亚洲欧洲日韩极速播放| 在线观看永久免费| 无码乱人伦一区二区亚洲| 国产99视频精品免费视频76| 免费国产一级特黄久久| 亚洲综合精品第一页|