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

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

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

    隨筆 - 4  文章 - 10  trackbacks - 0
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(1)

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    文章出自:http://m.tkk7.com/BlueDavy/archive/2006/03/27/37582.html
    一.
                

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

    閱讀本文前建議至少擁有Hibernate的一些基本知識(shí),因?yàn)楸疚牟粫?huì)去詳細(xì)介紹相關(guān)的基本知識(shí),最好就是先用Hibernate開發(fā)了一個(gè)HelloWorld^_^

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

    此文檔的PDF版本請(qǐng)到此下載:

    http://m.tkk7.com/Files/BlueDavy/Hibernate 實(shí)踐.rar

    本文允許轉(zhuǎn)載,但轉(zhuǎn)載時(shí)請(qǐng)注明作者以及來(lái)源。

    作者:BlueDavy

    來(lái)源:m.tkk7.com/BlueDavy

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

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

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

    2.1. lib

    2.1.1.        Hibernate lib

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

    2.2. xdoclet

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

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

    2.2.1.        Hibernate template

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

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

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

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

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

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

    2.2.2.        Ant task build

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

    在項(xiàng)目中我仍然采用 ant task 的方式來(lái)生成 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>

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

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

    2.3. Hibernate3 Tools

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

    2.4. HibernateUtil

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

    2.5. CommonDao

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

    三.              開發(fā)

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

    3.1. 實(shí)體的編寫

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

    在實(shí)體的編寫上應(yīng)該說(shuō)不會(huì)有什么問(wèn)題,只要仔細(xì)查看xdoclet關(guān)于hibernatedoclet部分的說(shuō)明即可完成。

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

    3.2. 實(shí)體的維護(hù)

    3.2.1.        新增 / 編輯 / 刪除

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

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

    u       Transient

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

    u       Detached

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

    User user=new User();

    user.setName(“bluedavy”);

    session.save(user);

    session.close();

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

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

    u       Persistent

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

    User user=new User();

    user.setName(“bluedavy”);

    session.save(user);

    user.getName();

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

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

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

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

    u       inverse

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

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

    當(dāng) org getUsers inverse=false 的情況:

    org.getUsers().add(user);

    dao.save(org);

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

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

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

    u       cascade

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

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

    cascade 的屬性值詳細(xì)見《 Hibernate reference 》。

    3.2.2.1.           一對(duì)一

    一對(duì)一的關(guān)聯(lián)維護(hù)在實(shí)際項(xiàng)目中使用不多,一對(duì)一在Hibernate中可采用兩種方式來(lái)構(gòu)成,一種是主鍵關(guān)聯(lián),一種是外鍵關(guān)聯(lián)。

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

    3.2.2.2.           一對(duì)多/多對(duì)一

    一對(duì)多/多對(duì)一的關(guān)聯(lián)維護(hù)在實(shí)際項(xiàng)目中使用是比較多的,在Hibernate中可采用多種方式來(lái)配置一對(duì)多的關(guān)聯(lián),如采用SetListBagMap等,具體在《Hibernate Reference》中都有詳細(xì)說(shuō)明。

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

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

    3.2.2.3.           多對(duì)多

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

    多對(duì)多的關(guān)聯(lián)也同樣可以采用SetList等多種方式來(lái)配置,具體在《Hibernate Reference》中也有詳細(xì)的說(shuō)明。

    多對(duì)多的關(guān)聯(lián)維護(hù)上沒(méi)有什么需要多說(shuō)的,在實(shí)踐過(guò)程中來(lái)看這塊不會(huì)出什么太多問(wèn)題,唯一需要注意的是合理設(shè)置cascade,這個(gè)要根據(jù)項(xiàng)目的實(shí)際情況而定。

    3.3. 實(shí)體的查詢

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

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

    3.3.1.        符合對(duì)象語(yǔ)言的查詢語(yǔ)句

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

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

    3.3.2.        占位符式的查詢

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

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

    3.3.2.1.           值類型

    3.3.2.1.1.      簡(jiǎn)單值

    舉例如下:

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

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

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

    query.setParameter(“yearold”,25);

    同樣, hibernate 也支持和 sql 完全相同的 ? 的方式,那么上面的語(yǔ)句以及注入?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)出來(lái)會(huì)稍有不同,不過(guò)如果按照對(duì)象觀點(diǎn)去看就很容易理解了,例如下面這句:

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

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

    List list=new ArrayList();

    list.add(“jerry”);

    list.add(“bluedavy”);

    query.setParameterList(“usernameList”,list);

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

    3.3.2.2.           實(shí)體類型

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

    3.3.2.2.1.      單實(shí)體

    單實(shí)體的查詢對(duì)應(yīng)到 sql 情況通常是在一對(duì)多的情況下通過(guò)多端查詢同時(shí)結(jié)合一端的一些過(guò)濾條件,在 sql 中通常采用 join 的方式來(lái)實(shí)現(xiàn)這個(gè),而在 Hibernate 中要實(shí)現(xiàn)這點(diǎn)就更容易了,舉例如下:

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

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

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

    query.setParameter(“yearold”,20);

    可以看到這樣的查詢語(yǔ)句比 sql 更簡(jiǎn)單多了,同時(shí)也更容易理解多了。

    3.3.2.2.2.      實(shí)體集合

    實(shí)體集合過(guò)濾形式的查詢?cè)趯?shí)際的項(xiàng)目中也經(jīng)常會(huì)碰到,仍然用上面的例子,但改為通過(guò) Organization 去查詢:

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

    是不是比 sql 簡(jiǎn)單多了,而且更容易理解呢, ^_^

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

    3.3.3.        NamedQuery

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

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

    session.getNamedQuery(queryname);

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

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

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

    ]]></ query >

    3.3.4.        Criteria

    條件查詢的 API 使得我們可以采用完全對(duì)象化的方式進(jìn)行實(shí)體的查詢,而不是通過(guò) hql 的方式,在實(shí)際項(xiàng)目中,使用 hql 的方式更為居多,畢竟寫起來(lái)更方便。

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

    3.3.5.        原生 SQL

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

    四.              設(shè)計(jì)

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

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

    4.1. 封裝

    4.1.1.        Component

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

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

    4.2. 繼承

    繼承使得我們可以對(duì)持久層中的對(duì)象進(jìn)行抽象,類如我們可以形成Person這個(gè)對(duì)象,而UserEmployee都繼承自這個(gè)對(duì)象。

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

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

    4.2.1.        單表策略

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

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

    4.2.2.        每個(gè)子類一張表

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

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

    4.2.3.        每個(gè)具體類一張表

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

    4.3. 多態(tài)

    4.3.1.        查詢

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

    五.              性能

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

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

    5.1. Lazy Load

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

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

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

    5.1.1.        OSIV

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

    5.2. Cache

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

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

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

    5.3. 高效的查詢語(yǔ)句

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

    5.3.1.        占位符式的查詢

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

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

    5.4. 一些配置

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

    5.5. 建議

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

    六.              測(cè)試

    6.1. 編寫專門的測(cè)試用的配置文件

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

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

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

    7.1. 事務(wù)

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

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

    7.2. 并發(fā)

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

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

    如果數(shù)據(jù)庫(kù)不支持用戶設(shè)置的鎖定模式,Hibernate將使用適當(dāng)?shù)奶娲J剑@一點(diǎn)可以確保應(yīng)用程序的可移植性。”。

    用戶可通過(guò)幾種方式來(lái)指定鎖定模式:

    u       Session.load() 的時(shí)候指定鎖定模式LockMode

    u       Session.lock()

    u       Query.setLockMode()

    八.              相關(guān)書籍

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

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

    8.1. Hibernate Reference

    這本沒(méi)什么說(shuō)的,必讀書籍,也許在讀的時(shí)候很多東西你不會(huì)覺得什么,但當(dāng)碰到一些確定方向的問(wèn)題時(shí),可以通過(guò)此書快速的查找到相應(yīng)的解決方案,感謝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 系列的書籍也沒(méi)啥多說(shuō)的,強(qiáng)烈推薦看看,盡管現(xiàn)在看起來(lái)版本有些老了,但里面很多的實(shí)踐思想仍然是非常值得學(xué)習(xí)的,網(wǎng)上應(yīng)該有很多電子版下載的地方。

    8.3. 《深入淺出Hibernate

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

    posted on 2007-08-15 21:14 冬天出走的豬 閱讀(366) 評(píng)論(0)  編輯  收藏 所屬分類: hibernate
    主站蜘蛛池模板: 色屁屁www影院免费观看视频| a毛片全部播放免费视频完整18| 国产一级淫片a免费播放口之| 国产精品免费久久久久影院| 亚洲一区二区中文| 永久在线免费观看| 久久人午夜亚洲精品无码区| 亚洲av永久无码精品秋霞电影影院 | 女人18毛片水真多免费播放| 一级中文字幕免费乱码专区| 亚洲人成综合在线播放| 亚洲阿v天堂在线2017免费| 免费无码VA一区二区三区| 深夜福利在线免费观看| 97久久精品亚洲中文字幕无码| 免费h成人黄漫画嘿咻破解版| 久久久高清免费视频| a级片免费在线观看| 日韩在线永久免费播放| 成人免费大片免费观看网站| a级毛片在线免费看| 久久久精品免费视频| 亚洲香蕉久久一区二区三区四区| 国产精品亚洲视频| 日韩免费高清视频| 成人无遮挡裸免费视频在线观看 | 亚洲一线产区二线产区精华| 亚洲成人午夜在线| 亚洲综合无码AV一区二区| 国产大片91精品免费看3| 成年女人看片免费视频播放器| 最近中文字幕mv免费高清视频8| 成人电影在线免费观看| 和老外3p爽粗大免费视频| 搜日本一区二区三区免费高清视频| 中文字幕看片在线a免费| 久久国产精品免费一区| 99免费视频观看| 日日操夜夜操免费视频| 在线亚洲午夜理论AV大片| 亚洲短视频在线观看|