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

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

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

    常言笑的家

    Spring, Hibernate, Struts, Ajax, RoR

    Hibernate實(shí)踐


    一.            

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

    閱讀本文前建議至少擁有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ì)、性能、測試以及推薦的相關(guān)書籍方面進(jìn)行講述,本篇文檔不會(huì)講的非常細(xì)致,只是根據(jù)自己在實(shí)踐時(shí)的經(jīng)驗(yàn)提出一些建議,關(guān)于細(xì)致以及具體的部分請參閱《Hibernate Reference》或推薦的相關(guān)書籍章節(jié)。

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

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

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

    作者:BlueDavy

    來源:m.tkk7.com/BlueDavy

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

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

    盡管Hibernate已經(jīng)封裝提供了很簡單的進(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)境中首要的問題,這部分可以從Hibernate的官方網(wǎng)站進(jìn)行下載,在其官方網(wǎng)站中同時(shí)提供了對于Hibernate所必須依賴的lib以及其他可選lib的介紹。

    2.2. xdoclet

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

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

    2.2.1.       Hibernate template

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

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

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

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

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

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

    2.2.2.       Ant task build

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

    在項(xiàng)目中我仍然采用ant task的方式來生成hbm.xmltarget如下所示:

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

    在搭建好了這樣的環(huán)境后,就可以在直接在eclipse中運(yùn)行ant文件中的這個(gè)target來生成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的使用,一般來說都會(huì)提供HibernateUtil這樣的類,這個(gè)類的作用主要是創(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的操作,但在實(shí)際的項(xiàng)目中還是需要提供一個(gè)通用的Dao,來簡化對于事務(wù)、異常處理以及session的操作,同時(shí)提供一些項(xiàng)目中需要的相關(guān)操作。

    三.             開發(fā)

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

    3.1. 實(shí)體的編寫

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

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

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

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

    3.2.1.       新增/編輯/刪除

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

    這個(gè)部分中需要注意的是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()后這個(gè)時(shí)候的user對象就處于Detached狀態(tài)之中了,如果想將這個(gè)對象變?yōu)?/span>Persistent狀態(tài),可以通過session.mergesession.saveOrUpdate()等方式來實(shí)現(xiàn)。

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

    u       Persistent

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

    User user=new User();

    user.setName(“bluedavy”);

    session.save(user);

    user.getName();

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

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

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

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

    u       inverse

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

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

    當(dāng)orggetUsersinverse=false的情況:

    org.getUsers().add(user);

    dao.save(org);

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

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

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

    u       cascade

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

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

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

    3.2.2.1.          一對一

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

    在這里我想說的一點(diǎn)就是關(guān)于inverse的設(shè)置,在一對多的情況下建議將一端的inverse設(shè)為true,而由多端去自動(dòng)維護(hù)關(guān)聯(lián)關(guān)系,為什么這樣做其實(shí)挺容易理解的,假設(shè)orguser為一對多的關(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ù)需求來實(shí)際決定。

    3.2.2.3.          多對多

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

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

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

    3.3. 實(shí)體的查詢

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

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

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

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

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

    3.3.2.       占位符式的查詢

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

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

    3.3.2.1.          值類型

    3.3.2.1.1.      簡單值

    舉例如下:

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

    這就是一個(gè)常見的簡單值的占位符式的查詢,通過這樣的方式就可以把值注入到參數(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)出來會(huì)稍有不同,不過如果按照對象觀點(diǎn)去看就很容易理解了,例如下面這句:

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

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

    List list=new ArrayList();

    list.add(“jerry”);

    list.add(“bluedavy”);

    query.setParameterList(“usernameList”,list);

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

    3.3.2.2.          實(shí)體類型

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

    3.3.2.2.1.      單實(shí)體

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

    UserOrganization是一對多,現(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);

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

    3.3.2.2.2.      實(shí)體集合

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

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

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

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

    3.3.3.       NamedQuery

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

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

    session.getNamedQuery(queryname);

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

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

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

    ]]></query>

    3.3.4.       Criteria

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

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

    3.3.5.       原生SQL

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

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

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

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

    4.1. 封裝

    4.1.1.       Component

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

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

    4.2. 繼承

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

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

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

    4.2.1.       單表策略

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

    Hibernate中通常將子類定義為@hibernate.subclass的方式來實(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í)對于抽象類,需要指明其abstract=”true”

    4.3. 多態(tài)

    4.3.1.       查詢

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

    五.             性能

    Hibernate作為ORM工具,從性能上來講帶給了很多人憂慮,但我覺得Hibernate在性能上也許會(huì)帶來少許的降低,但如果對于不能合理設(shè)計(jì)數(shù)據(jù)庫和使用SQL的人來說,我覺得Hibernate反倒能提高性能,除非是在一些特殊的場合,如報(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中的集合以及集合中對象的屬性、集合,這樣看過去很容易看出,如果對象的關(guān)聯(lián)結(jié)構(gòu)有深層次的話,最后搞不好整個(gè)庫都被加載出來了,而在實(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ù)庫中加載,當(dāng)然,集合也同樣如此。

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

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

    5.1.1.       OSIV

    OSIVOpen 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以后的版本默認(rèn)使用的是Ehcache,也可以切換為OscacheJbossCache,對我而言最重要的區(qū)別在于對于cluster的支持上。

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

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

    5.3. 高效的查詢語句

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

    5.3.1.       占位符式的查詢

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

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

    5.4. 一些配置

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

    5.5. 建議

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

    六.             測試

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

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

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

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

    7.1. 事務(wù)

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

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

    7.2. 并發(fā)

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

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

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

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

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

    u       Session.lock()

    u       Query.setLockMode()

    八.             相關(guān)書籍

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

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

    8.1. Hibernate Reference

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

    8.3. 《深入淺出Hibernate

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

    posted on 2007-01-18 14:20 常言笑 閱讀(403) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫

    My Links

    Blog Stats

    常用鏈接

    留言簿(5)

    隨筆分類

    隨筆檔案

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 一级白嫩美女毛片免费| 日韩吃奶摸下AA片免费观看| 亚洲?V乱码久久精品蜜桃 | 无码毛片一区二区三区视频免费播放 | 国产亚洲综合色就色| 一级毛片视频免费观看| 国产精品酒店视频免费看| 色噜噜亚洲男人的天堂| 亚洲免费一级视频| 亚洲美女中文字幕| 9277手机在线视频观看免费| 亚洲精品国产成人99久久| 国产自国产自愉自愉免费24区| 久久久久无码专区亚洲av| 免费福利资源站在线视频| 亚洲AⅤ永久无码精品AA| 黄色毛片免费网站| 亚洲国产精品成人久久蜜臀| 国产亚洲福利精品一区二区| 日本人的色道www免费一区| 亚洲1区2区3区精华液| 国产高清免费的视频| 亚洲精品一卡2卡3卡四卡乱码| 免费高清在线影片一区| 亚洲人成电影网站色| 免费无码看av的网站| 欧洲亚洲国产精华液| 国产免费观看网站| 曰批免费视频播放免费| 四虎精品亚洲一区二区三区| 日韩在线视频线视频免费网站| 亚洲精品无码久久久| 中文字幕看片在线a免费| 亚洲爆乳精品无码一区二区三区| 国产一级黄片儿免费看| 亚洲AV综合色区无码一区爱AV | 香蕉视频在线观看免费国产婷婷| 亚洲欧美日韩国产精品一区| 四虎在线免费播放| 免费看又黄又爽又猛的视频软件| 亚洲国产精品人人做人人爽|