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

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

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

    每日一得

    不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速開發
    最近關心的內容:SSH,seam,flex,敏捷,TDD
    本站的官方站點是:顛覆軟件

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      220 隨筆 :: 9 文章 :: 421 評論 :: 0 Trackbacks

    #

    越來越發現其實掌握 hibernate并不容易,Spring用起來其實簡單多了,但是在用hibernate的時候真的是需要一定的時間積累,對一個項目組來說如果采用hibernate最好有一個對hibernate比較清楚的人否則碰到問題就會成為項目的風險。
    我想告訴各位的是,掌握hibernate可能比你預期的難多了,當你輕松的告訴我,hibernate很簡單的時候該是你自己多反省了. (只有一種情況例外,你是一個牛人)

    好了,一個引子廢話那么多,其實今天只是想先說一說hibernate里的Fetch的作用.

    大家都知道,在hibernate里為了性能考慮,引進了lazy的概念,這里我們以Parent和Child為模型來說明,

    public?class?Parent?implements?Serializable?{

    ????
    /**?identifier?field?*/
    ????
    private?Long?id;

    ????
    /**?persistent?field?*/
    ????
    private?List?childs;

    ????
    //skip?all?getter/setter?method

    ??
    }??



    public?class?Child?implements?Serializable?{

    ????
    /**?identifier?field?*/
    ????
    private?Long?id;

    ????
    /**?persistent?field?*/
    ????
    private?net.foxlog.model.Parent?parent;

    ??? //skip all getter/setter method

    }

    在我們查詢Parent對象的時候,默認只有Parent的內容,并不包含childs的信息,如果在Parent.hbm.xml里設置lazy="false"的話才同時取出關聯的所有childs內容.

    問題是我既想要hibernate默認的性能又想要臨時的靈活性該怎么辦?? 這就是fetch的功能。我們可以把fetch與lazy="true"的關系類比為事務當中的編程式事務與聲明式事務,不太準確,但是大概是這個意思。

    總值,fetch就是在代碼這一層給你一個主動抓取得機會.

    Parent?parent?=?(Parent)hibernateTemplate.execute(new?HibernateCallback()?{
    ????????????
    public?Object?doInHibernate(Session?session)?throws?HibernateException,?SQLException?{
    ????????????????Query?q?
    =?session.createQuery(
    ????????????????????????
    "from?Parent?as?parent?"+
    ????????????????????????????????
    "?left?outer?join?fetch?parent.childs?"?+
    ????????????????????????????????
    "?where?parent.id?=?:id"
    ????????????????);
    ????????????????q.setParameter(
    "id",new?Long(15));
    ????????????????
    return?(Parent)q.uniqueResult();
    ????????????}

    ????????});

    ????????Assert.assertTrue(parent.getChilds().size()?
    >?0);


    你可以在lazy="true"的情況下把fetch去掉,就會報異常. 當然,如果lazy="false"就不需要fetch了


    有一個問題,使用Fetch會有重復記錄的現象發生,我們可以理解為Fetch實際上不是為Parent服務的,而是為Child服務的.所以直接取Parent會有不匹配的問題.



    參考一下下面的這篇文章
    Hibernate集合初始化

    ======================================================================

    update:以上有些結論錯誤,實際上在hibernate3.2.1版本下測試,可以不出現重復記錄,

    public?void?testNPlusOne()?throws?Exception{
    ????????List?list?
    =?(List)hibernateTemplate.execute(new?HibernateCallback()?{
    ????????????
    public?Object?doInHibernate(Session?session)?throws?HibernateException,?SQLException?{
    ????????????????Query?q?
    =?session.createQuery(
    ????????????????????????
    "select?distinct?p?from?net.foxlog.model.Parent?p?inner?join?fetch?p.childs"
    ????????????????);
    ????????????????
    return?q.list();
    ????????????}

    ????????});

    ????????
    //((Parent)(list.get(0))).getChilds();
    ????????System.out.println("list?size?=?"?+?list.size());
    ????????
    for(int?i=0;i<list.size();i++){
    ????????????Parent?p?
    =?(Parent)list.get(i);
    ????????????System.out.println(
    "===parent?=?"?+?p);
    ????????????System.out.println(
    "===parent's?child's?length?=?"?+?p.getChilds().size());
    ????????}

    ????}


    打印結果如下:
    Hibernate:?select?distinct?parent0_.id?as?id2_0_,?childs1_.id?as?id0_1_,?childs1_.parent_id?as?parent2_0_1_,?childs1_.parent_id?as?parent2_0__,?childs1_.id?as?id0__?from?parent?parent0_?inner?join?child?childs1_?on?parent0_.id=childs1_.parent_id
    list?size?
    =?3
    ===parent?=?net.foxlog.model.Parent@1401d28[id=14]
    ===parent's?child's?length?=?1
    ===parent?=?net.foxlog.model.Parent@14e0e90[id=15]
    ===parent's?child's?length?=?2
    ===parent?=?net.foxlog.model.Parent@62610b[id=17]
    ===parent's?child's?length?=?3

    另外,如果用open session in view模式的話一般不用fetch,但首先推薦fetch,如果非用的話因為有N+1的現象,所以可以結合batch模式來改善下性能.


    posted @ 2006-12-01 13:01 Alex 閱讀(19372) | 評論 (7)編輯 收藏

    LDAPChina序言:這篇文章是互聯網上最流行的一篇介紹LDAP基礎知識的文章,本文作者Michael DonnellyLDAPMAN.org的站長。由于本文譯文較長,我們將其分為兩部分,第一部分介紹LDAP概論,第二部分介紹LDAP基礎知識。感謝網友Brimmer翻譯此文。

    如 果你在計算機行業工作,那么對LDAP可能早有耳聞了。想深入地了解LDAP嗎?那么可以好好地讀一下這篇文章。這篇介紹性的文章是一系列介紹如何在企業 中設計、實現和集成LDAP環境的文章的頭一篇。主要是先讓你熟悉一下LDAP的基本概念,那些比較困難的細節問題將放到以后討論。在這篇文章中我們將要 介紹:

    什么是LDAP?
    什么時候該用LDAP存儲數據?

    現 在LDAP技術不僅發展得很快而且也是激動人心的。在企業范圍內實現LDAP可以讓運行在幾乎所有計算機平臺上的所有的應用程序從LDAP目錄中獲取信 息。LDAP目錄中可以存儲各種類型的數據:電子郵件地址、郵件路由信息、人力資源數據、公用密匙、聯系人列表,等等。通過把LDAP目錄作為系統集成中 的一個重要環節,可以簡化員工在企業內部查詢信息的步驟,甚至連主要的數據源都可以放在任何地方。如果Oracle、Sybase、Informix或 Microsoft SQL數據庫中已經存儲了類似的數據,那么LDAP和這些數據庫到底有什么不同呢?是什么讓它更具優勢?請繼續讀下去吧!


    什么是LDAP?

    LDAP 的英文全稱是Lightweight Directory Access Protocol,一般都簡稱為LDAP。它是基于X.500標準的,但是簡單多了并且可以根據需要定制。與X.500不同,LDAP支持TCP/IP, 這對訪問Internet是必須的。LDAP的核心規范在RFC中都有定義,所有與LDAP相關的RFC都可以在LDAPChina.com RFC專欄中找到。

    怎么使用LDAP這個術語呢?

    在 日常交談中,你可能會聽到有些人這么說:“我們要把那些東西存在LDAP中嗎?”,或者“從LDAP數據庫中取出那些數據!”,又或者“我們怎么把 LDAP和關系型數據庫集成在一起?”。嚴格地說,LDAP根本不是數據庫而是用來訪問存儲在信息目錄(也就是LDAP目錄)中的信息的協議。更為確切和正式的說法應該是象這樣的:“通過使用LDAP,可以在信息目錄的正確位置讀?。ɑ虼鎯Γ祿薄5?,也沒有必要吹毛求疵,盡管表達得不夠準確,我們也都知道對方在說什么。

    LDAP目錄是數據庫嗎?

    就 象Sybase、Oracle、Informix或Microsoft的數據庫管理系統(DBMS)是用于處理查詢和更新關系型數據庫那樣,LDAP服務 器也是用來處理查詢和更新LDAP目錄的。換句話來說LDAP目錄也是一種類型的數據庫,但是不是關系型數據庫。不象被設計成每分鐘需要處理成百上千條數 據變化的數據庫,例如:在電子商務中經常用到的在線交易處理(OLTP)系統,LDAP主要是優化數據讀取的性能。

    LDAP目錄的優勢

    現在該說說LDAP目錄到底有些什么優勢了?,F在LDAP的流行是很多因素共同作用的結果。我在這里說的不過是一些基本的原因,請你注意一下這不過是一小部分原因。

    可能LDAP最大的優勢是:可以在任何計算機平臺上,用很容易獲得的而且數目不斷增加的LDAP的客戶端程序訪問LDAP目錄。而且也很容易定制應用程序為它加上LDAP的支持。

    LDAP 協議是跨平臺的和標準的協議,因此應用程序就不用為LDAP目錄放在什么樣的服務器上操心了。實際上,LDAP得到了業界的廣泛認可,因為它是 Internet的標準。產商都很愿意在產品中加入對LDAP的支持,因為他們根本不用考慮另一端(客戶端或服務端)是怎么樣的。LDAP服務器可以是任 何一個開發源代碼或商用的LDAP目錄服務器(或者還可能是具有LDAP界面的關系型數據庫),因為可以用同樣的協議、客戶端連接軟件包和查詢命令與 LDAP服務器進行交互。與LDAP不同的是,如果軟件產商想在軟件產品中集成對DBMS的支持,那么通常都要對每一個數據庫服務器單獨定制。

    不象很多商用的關系型數據庫,你不必為LDAP的每一個客戶端連接或許可協議付費。

    大多數的LDAP服務器安裝起來很簡單,也容易維護和優化。

    LDAP服務器可以用“推”或“拉”的方法復制部分或全部數據,例如:可以把數據“推”到遠程的辦公室,以增加數據的安全性。復制技術是內置在LDAP服務器中的而且很容易配置。如果要在DBMS中使用相同的復制功能,數據庫產商就會要你支付額外的費用,而且也很難管理。

    LDAP 允許你根據需要使用ACI(一般都稱為ACL或者訪問控制列表)控制對數據讀和寫的權限。例如,設備管理員可以有權改變員工的工作地點和辦公室號碼,但是 不允許改變記錄中其它的域。ACI可以根據誰訪問數據、訪問什么數據、數據存在什么地方以及其它對數據進行訪問控制。因為這些都是由LDAP目錄服務器完 成的,所以不用擔心在客戶端的應用程序上是否要進行安全檢查。

    LDAP對于存儲下面這樣的信息最為有用,也就是數據需要從不同的地點讀取,但是不需要經常更新。例如,這些信息存儲在LDAP目錄中是十分有效的:

    • 公司員工的電話號碼簿和組織結構圖
    • 客戶的聯系信息
    • 計算機管理需要的信息,包括NIS映射、email假名,等等
    • 軟件包的配置信息
    • 公用證書和安全密匙

    什么時候該用LDAP存儲數據?

    大 多數的LDAP服務器都為讀密集型的操作進行專門的優化。因此,當從LDAP服務器中讀取數據的時候會比從專門為OLTP優化的關系型數據庫中讀取數據快 一個數量級。也是因為專門為讀的性能進行優化,大多數的LDAP目錄服務器并不適合存儲需要經常改變的數據。例如,用LDAP服務器來存儲電話號碼是一個 很好的選擇,但是它不能作為電子商務站點的數據庫服務器。

    如果下面每一個問題的答案都是“是”,那么把數據存在LDAP中就是一個好主意。

    • 需要在任何平臺上都能讀取數據嗎?
    • 每一個單獨的記錄項是不是每一天都只有很少的改變?
    • 可以把數據保存在平面數據庫(flat database)而不是關系型數據庫中嗎?換句話來說,也就是不管什么范式不范式的,把所有東西都存在一個記錄中(差不多只要滿足第一范式)。

    最 后一個問題可能會唬住一些人,其實用平面數據庫去存儲一些關系型的數據也是很一般的。例如,一條公司員工的記錄就可以包含經理的登錄名。用LDAP來存儲 這類信息是很方便的。一個簡單的判斷方法:如果可以把數據保存在一張張的卡片里,就可以很容易地把它存在LDAP目錄里。


    接上文

    LDAP目錄樹的結構
    單條LDAP記錄
    定制目錄的對象類
    一個LDAP單個條目的例子
    LDAP復制
    安全和訪問控制

    LDAP目錄樹的結構

    LDAP 目錄以樹狀的層次結構來存儲數據。如果你對自頂向下的DNS樹或UNIX文件的目錄樹比較熟悉,也就很容易掌握LDAP目錄樹這個概念了。就象DNS的主 機名那樣,LDAP目錄記錄的分辨名(Distinguished Name,簡稱DN)是用來讀取單條記錄,以及回溯到樹的頂部。后面會做詳細地介紹。

    為什么要用層次結構來組織數據呢?原因是多方面的。下面是可能遇到的一些情況:

    • 如果你想把所有的美國客戶的聯系信息都“推”到位于到西雅圖辦公室(負責營銷)的LDAP服務器上, 但是你不想把公司的資產管理信息“推”到那里。
    • 你可能想根據目錄樹的結構給予不同的員工組不同的權限。在下面的例子里,資產管理組對“asset-mgmt”部分有完全的訪問權限,但是不能訪問其它地方。
    • 把LDAP存儲和復制功能結合起來,可以定制目錄樹的結構以降低對WAN帶寬的要求。位于西雅圖的營銷辦公室需要每分鐘更新的美國銷售狀況的信息,但是歐洲的銷售情況就只要每小時更新一次就行了。

    刨根問底:基準DN

    LDAP目錄樹的最頂部就是根,也就是所謂的“基準DN”?;鶞蔇N通常使用下面列出的三種格式之一。假定我在名為FooBar的電子商務公司工作,這家公司在Internet上的名字是foobar.com。

    o="FooBar, Inc.", c=US

    (以X.500格式表示的基準DN)

    在 這個例子中,o=FooBar, Inc. 表示組織名,在這里就是公司名的同義詞。c=US 表示公司的總部在美國。以前,一般都用這種方式來表示基準DN。但是事物總是在不斷變化的,現在所有的公司都已經(或計劃)上Internet上。隨著 Internet的全球化,在基準DN中使用國家代碼很容易讓人產生混淆。現在,X.500格式發展成下面列出的兩種格式。

    o=foobar.com

    (用公司的Internet地址表示的基準DN)

    這種格式很直觀,用公司的域名作為基準DN。這也是現在最常用的格式。

    dc=foobar, dc=com

    (用DNS域名的不同部分組成的基準DN)

    就 象上面那一種格式,這種格式也是以DNS域名為基礎的,但是上面那種格式不改變域名(也就更易讀),而這種格式把域名:foobar.com分成兩部分 dc=foobar, dc=com。在理論上,這種格式可能會更靈活一點,但是對于最終用戶來說也更難記憶一點。考慮一下foobar.com這個例子。當 foobar.com和gizmo.com合并之后,可以簡單的把“dc=com”當作基準DN。把新的記錄放到已經存在的dc=gizmo, dc=com目錄下,這樣就簡化了很多工作(當然,如果foobar.com和wocket.edu合并,這個方法就不能用了)。如果LDAP服務器是新 安裝的,我建議你使用這種格式。再請注意一下,如果你打算使用活動目錄(Actrive Directory),Microsoft已經限制你必須使用這種格式。

    更上一層樓:在目錄樹中怎么組織數據

    在UNIX文件系統中,最頂層是根目錄(root)。在根目錄的下面有很多的文件和目錄。象上面介紹的那樣,LDAP目錄也是用

    posted @ 2006-11-30 20:45 Alex| 編輯 收藏

    key words:jotspot,wiki,項目管理

    最近聽說了jotspot,這個東西確實很好,原來一直打算自己建立一個wiki,作一些公司項目資源的管理,進度管理,以及提供其他團隊成員了解項目信息的窗口,原來打算用jspwiki,可是建在哪呢? 在我的筆記本上還是公司的服務器上,似乎都不是很好,還是建在jotspot上比較好。zheng
    給我看了一個截圖:

    jotspot_project.gif


    功能還挺強大,我想做我的日常項目管理應該夠了


    posted @ 2006-11-09 22:03 Alex 閱讀(714) | 評論 (2)編輯 收藏


    key words:google搜索技巧,in site,inurl,filetype

    最常用的是下面這個

    IDEA?in?site:blogjava.net?inurl:Alex filetype:ppt


    下面轉錄一篇
    玩轉GOOGLE的十九招秘技


    第一招:

      在輸入多個詞的時候,Google默認的是并且式的查詢,如果想使用或者式的查詢,使用OR,例如:java OR c++

    第二招
      google是不區分大小寫的,搜索Java和搜索JAVA或者java是完全一樣的。

      第三招
      邏輯關系優先級使用圓括號,例如查找包含java和(JVM或者虛擬機):Java (JVM或者虛擬機)。

      第四招
      要搜索詞組需要使用引號括起來,例如搜索Java虛擬機可以使用:"Java虛擬機"。

      第五招
      要想在搜索結果中不包含某些結果可以使用減號,例如搜索java又不包含培訓可以使用:java -培訓。

      第六招
      一般情況下是不能使用通配符的,通配符只能使用在詞組中,例如:"使用*模式"。

      第七招
      只在網頁的標題(即html的title指定的部分)內搜索指定的內容,例如:intitle:java。
    第八招
      只在網頁的url內搜索指定的內容,例如:inurl:java。

      第九招
      只在網頁的正文內搜索指定的內容(忽略鏈接文字、標題和url),例如:intext:java。

      第十招
      只在鏈接文字(鏈接Java研究組織的鏈接文字就是Java研究組織)內搜索指定的內容,例如:inanchor:java。

      第十一招
      只在指定的網站內搜索指定的內容,可以是某個具體的網站或者是某個域名分類,例如:site:javaresearch.org或者site:org。

      第十二招
      只在指定的文件格式內搜索指定的內容,需要注意google只能支持有限的常用文本格式,包含一些諸如doc,xsl,ppt,pdf之類的富文本格式,例如:filetype:htm。

      第十三招
      google在檢索的時候對于輸入的內容的順序是敏感的,如果找不到合適的結果可以試試改變一下搜索的關鍵字的順序。


      第十四招
      在搜索多個關鍵字構成的內容時可以試試加引號和不加引號兩者情況,結果可能有很大的差異,例如:java虛擬機和"java虛擬機"。

      第十五招
      搜索的策略可以采用先多后少,假設你想搜索Java的的command模式的例子,可以先試試java command pattern,然后試試java pattern或者java command,每次減少的那個關鍵字應該是你認為相對不重要的一個。
    第十六招
      對于搜索中文而言,搜索“虛擬機”和搜索“虛擬機”是不同的,后者一般比前者的結果多并且相關性差一些,一般情況下你應該在各個詞之間加空格,而在詞內不加空格,這樣得到的結果一般更好。

      第十七招
      一個關鍵字可以重復兩次,對結果的排名和數量也會有影響,重復兩次以上好像就沒有什么影響了,例如搜索"internet"和搜索"internet internet"的結果是不同的。

      第十八招
      搜索內容最多只能包含十個單詞,包括搜索intitle之類的選項,多出的部分被忽略。

      第十九招
      對于intitle,inurl,intext,inanchor和site之類的搜索選項一次不要使用多次,否則要么不是你想要的結果,要么根本就沒有結果,混合使用這些選項是合法的,但是規則很復雜。

    posted @ 2006-11-09 21:49 Alex 閱讀(981) | 評論 (0)編輯 收藏

    key words:mappingResources,通配符,mappingDirectoryLocations

    平時寫mapping的文件需要一個一個的放到配置文件里,比如
    ???1.?<property?name="mappingResources">??
    ???2.?????????????
    <list>??
    ???3.?????????????????
    <value>net/foxlog/model/Classes.hbm.xml</value>??
    ???4.?????????????????
    <value>net/foxlog/model/Parent.hbm.xml</value>??
    ???5.?????????????????
    <value>net/foxlog/model/Child.hbm.xml</value>??
    ???6.?????????????????
    <value>net/foxlog/model/User.hbm.xml</value>??
    ???7.?????????????
    </list>??
    ???8.?????????
    </property>??


    可以用更一步到位的方法:

    ???1.?<property?name="mappingDirectoryLocations">??
    ???2.?????????????
    <list>??
    ???3.?????????????????
    <value>classpath*:/org/springside/bookstore/commons/model/hbm</value>??
    ???4.?????????????
    </list>??
    ???5.?????????
    </property>??

    posted @ 2006-11-09 21:00 Alex 閱讀(5037) | 評論 (0)編輯 收藏

    key words:hibernate,復合主鍵,composite-id



    基于業務需求,您會需要使用兩個字段來作復合主鍵,例如在User數據表中,您也許會使用"name""phone"兩個字段來定義復合主鍵。

    假設您這么建立User表格:

    CREATE?TABLE?user?(

    ????name?
    VARCHAR(100)?NOT?NULL,

    ????phone?
    VARCHAR(50)?NOT?NULL,

    ????age?
    INT,

    ????
    PRIMARY?KEY(name,?phone)

    );

    在表格中,"name""age"被定義為復合主鍵,在映像時,您可以讓User類別直接帶有"name""age"這兩個屬性,而Hibernate要求復合主鍵類別要實作Serializable接口,并定義equals()hashCode()方法:

    User.java

    package?onlyfun.caterpillar;

    ?

    import?java.io.Serializable;

    import?org.apache.commons.lang.builder.EqualsBuilder;

    import?org.apache.commons.lang.builder.HashCodeBuilder;

    ?

    //?復合主鍵類的對應類別必須實作Serializable接口

    public?class?User?implements?Serializable?{

    ????
    private?String?name;

    ????
    private?String?phone;

    ????
    private?Integer?age;

    ???

    ????
    public?User()?{

    ????}

    ?

    ????
    public?Integer?getAge()?{

    ????????
    return?age;

    ????}

    ?

    ????
    public?void?setAge(Integer?age)?{

    ????????
    this.age?=?age;

    ????}

    ?

    ????
    public?String?getName()?{

    ????????
    return?name;

    ????}

    ?

    ????
    public?void?setName(String?name)?{

    ????????
    this.name?=?name;

    ????}

    ?

    ????
    public?String?getPhone()?{

    ????????
    return?phone;

    ????}

    ?

    ????
    public?void?setPhone(String?phone)?{

    ????????
    this.phone?=?phone;

    ????}

    ???

    ????
    //?必須重新定義equals()與hashCode()

    ????
    public?boolean?equals(Object?obj)?{

    ????????
    if(obj?==?this)?{

    ????????????
    return?true;

    ????????}

    ???????

    ????????
    if(!(obj?instanceof?User))?{

    ????????????
    return?false;

    ????????}

    ???????

    ????????User?user?
    =?(User)?obj;

    ????????
    return?new?EqualsBuilder()

    ?????????????????.append(
    this.name,?user.getName())

    ?????????????????.append(
    this.phone,?user.getPhone())

    ?????????????????.isEquals();

    ???????

    ????}

    ???

    ????
    public?int?hashCode()?{

    ????????
    return?new?HashCodeBuilder()

    ?????????????????.append(
    this.name)

    ?????????????????.append(
    this.phone)

    ?????????????????.toHashCode();

    ????}

    }

    equals()hashCode()方法被用作兩筆不同數據的識別依據;接著您可以使用<composite-id>在映射文件中定義復合主鍵與對象的屬性對應:

    User.hbm.xml

    <?xml?version="1.0"?encoding="utf-8"?>

    <!DOCTYPE?hibernate-mapping

    ????PUBLIC?"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"

    ????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
    >

    ?

    <hibernate-mapping>

    ?

    ????
    <class?name="onlyfun.caterpillar.User"?table="user">

    ????????
    <composite-id>

    ????????????
    <key-property?name="name"

    ??????????????????????????column
    ="name"

    ??????????????????????????type
    ="java.lang.String"/>

    ????????????
    <key-property?name="phone"

    ??????????????????????????column
    ="phone"

    ??????????????????????????type
    ="java.lang.String"/>

    ????????
    </composite-id>

    ?

    ????????
    <property?name="age"?column="age"?type="java.lang.Integer"/>

    ???

    ????
    </class>

    </hibernate-mapping>

    在儲存數據方面,復合主鍵的儲存沒什么區別,現在的問題在于如何依據復合主鍵來查詢數據,例如使用load()方法,您可以創建一個User實例,并設定復合主鍵對應的屬性,接著再透過load()查詢對應的數據,例如:

    User?user?=?new?User();

    user.setName(
    "bush");

    user.setPhone(
    "0970123456");

    ???????

    Session?session?
    =?sessionFactory.openSession();

    //?以實例設定復合主鍵并加載對應的數據

    user?
    =?(User)?session.load(User.class,?user);

    ???????

    System.out.println(user.getAge()?
    +?"\t"?+

    ??????????????????????????????????user.getName()?
    +?"\t"?+

    ??????????????????????????????????user.getPhone());

    session.close();

    ?

    ?

    可以將主鍵的信息獨立為一個類別,例如:

    UserPK.java

    package?onlyfun.caterpillar;

    ?

    import?java.io.Serializable;

    ?

    import?org.apache.commons.lang.builder.EqualsBuilder;

    import?org.apache.commons.lang.builder.HashCodeBuilder;

    ?

    public?class?UserPK?implements?Serializable?{

    ????
    private?String?name;

    ????
    private?String?phone;

    ?

    ????
    public?String?getName()?{

    ????????
    return?name;

    ????}

    ?

    ????
    public?void?setName(String?name)?{

    ????????
    this.name?=?name;

    ????}

    ?

    ????
    public?String?getPhone()?{

    ????????
    return?phone;

    ????}

    ?

    ????
    public?void?setPhone(String?phone)?{

    ????????
    this.phone?=?phone;

    ????}

    ???

    ????
    public?boolean?equals(Object?obj)?{

    ????????
    if(obj?==?this)?{

    ????????????
    return?true;

    ????????}

    ???????

    ????????
    if(!(obj?instanceof?User))?{

    ????????????
    return?false;

    ????????}

    ???????

    ????????UserPK?pk?
    =?(UserPK)?obj;

    ????????
    return?new?EqualsBuilder()

    ?????????????????.append(
    this.name,?pk.getName())

    ?????????????????.append(
    this.phone,?pk.getPhone())

    ?????????????????.isEquals();

    ???????

    ????}

    ???

    ????
    public?int?hashCode()?{

    ????????
    return?new?HashCodeBuilder()

    ?????????????????.append(
    this.name)

    ?????????????????.append(
    this.phone)

    ?????????????????.toHashCode();

    ????}

    }

    現在User類別的主鍵信息被分離出來了,例如:

    User.java

    package?onlyfun.caterpillar;

    ?

    import?java.io.Serializable;

    ?

    public?class?User?implements?Serializable?{

    ????
    private?UserPK?userPK;?//?主鍵

    ????
    private?Integer?age;

    ???

    ????
    public?User()?{

    ????}

    ?

    ????
    public?UserPK?getUserPK()?{

    ????????
    return?userPK;

    ????}

    ?

    ????
    public?void?setUserPK(UserPK?userPK)?{

    ????????
    this.userPK?=?userPK;

    ????}

    ?

    ????
    public?Integer?getAge()?{

    ????????
    return?age;

    ????}

    ?

    ????
    public?void?setAge(Integer?age)?{

    ????????
    this.age?=?age;

    ????}

    }

    在映像文件方面,需要指定主鍵類的信息,例如:

    User.hbm.xml

    <?xml?version="1.0"?encoding="utf-8"?>

    <!DOCTYPE?hibernate-mapping

    ????PUBLIC?"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"

    ????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
    >

    ?

    <hibernate-mapping>

    ?

    ????
    <class?name="onlyfun.caterpillar.User"?table="user">

    ????????
    <composite-id?name="userPK"

    ??????????????????????class
    ="onlyfun.caterpillar.UserPK"

    ??????????????????????unsaved-value
    ="any">

    ????????????
    <key-property?name="name"

    ??????????????????????????column
    ="name"

    ??????????????????????????type
    ="java.lang.String"/>

    ????????????
    <key-property?name="phone"

    ??????????????????????????column
    ="phone"

    ??????????????????????????type
    ="java.lang.String"/>

    ????????
    </composite-id>

    ???????

    ????????
    <property?name="age"?column="age"?type="java.lang.Integer"/>

    ???

    ????
    </class>

    ?

    </hibernate-mapping>

    在查詢數據時,必須指定主鍵信息,例如:

    UserPK?pk?=?new?UserPK();

    pk.setName(
    "bush");

    pk.setPhone(
    "0970123456");

    ??????

    Session?session?
    =?sessionFactory.openSession();

    //?以主鍵類實例設定復合主鍵并加載對應的數據

    User?user?
    =?(User)?session.load(User.class,?pk);

    ??????

    System.out.println(user.getAge()?
    +?"\t"?+

    ??????????????????????????????????user.getUserPK().getName()?
    +?"\t"?+

    ??????????????????????????????????user.getUserPK().getPhone());

    session.close();

    ?


    =================================================
    再參考robbin的一篇文章
    一個簡單的復合主鍵的做關聯類的例子??
    posted @ 2006-11-09 19:22 Alex 閱讀(12923) | 評論 (5)編輯 收藏

    key words:jdk錯誤,Unsupported major.minor version

    今天用一個工作流的產品,非要用jdk1.4的版本,沒辦法,只好切換回來,但是換回來后打開頁面jsp出錯,提示Unsupported major.minor version 49.0錯誤,到網上查了一下,49.0錯誤屬于jdk1.5的錯誤,但是我的jdk1.5已經刪除了???怎么回事呢?

    最后想起來,可能是jboss中的1.5 版本產生臨時文件class文件刪除,刪除后OK


    資料:Unsupported major.minor version 49.0
    posted @ 2006-11-08 10:13 Alex 閱讀(577) | 評論 (2)編輯 收藏

    key words:hibernate,load,session.get,session.load()

    public?class?Parent?implements?Serializable?{

    ????
    /**?identifier?field?*/
    ????
    private?Long?id;

    ????
    /**?persistent?field?*/
    ????
    private?List?childs;

    ????
    /**?full?constructor?*/
    ????
    public?Parent(Long?id,?List?childs)?{
    ????????
    this.id?=?id;
    ????????
    this.childs?=?childs;
    ????}

    ????
    /**?default?constructor?*/
    ????
    public?Parent()?{
    ????}

    ????
    /**?
    ?????*????????????@hibernate.id
    ?????*?????????????generator-class="assigned"
    ?????*?????????????type="java.lang.Long"
    ?????*?????????????column="id"
    ?????*
    ?????
    */
    ????
    public?Long?getId()?{
    ????????
    return?this.id;
    ????}

    ????
    public?void?setId(Long?id)?{
    ????????
    this.id?=?id;
    ????}

    ????
    /**
    ?????*????????????@hibernate.set
    ?????*?????????????lazy="true"
    ?????*?????????????inverse="true"
    ?????*?????????????cascade="none"
    ?????*????????????@hibernate.collection-key
    ?????*?????????????column="parent_id"
    ?????*????????????@hibernate.collection-one-to-many
    ?????*?????????????class="net.foxlog.model.Child"
    ?????*?????????
    ?????
    */
    ????
    public?List?getChilds()?{
    ????????
    return?this.childs;
    ????}

    ????
    public?void?setChilds(List?childs)?{
    ????????
    this.childs?=?childs;
    ????}

    ????
    public?String?toString()?{
    ????????
    return?new?ToStringBuilder(this)
    ????????????.append(
    "id",?getId())
    ????????????.toString();
    ????}

    ????
    public?boolean?equals(Object?other)?{
    ????????
    if?(?!(other?instanceof?Parent)?)?return?false;
    ????????Parent?castOther?
    =?(Parent)?other;
    ????????
    return?new?EqualsBuilder()
    ????????????.append(
    this.getId(),?castOther.getId())
    ????????????.isEquals();
    ????}

    ????
    public?int?hashCode()?{
    ????????
    return?new?HashCodeBuilder()
    ????????????.append(getId())
    ????????????.toHashCode();
    ????}

    }


    Parent?parent?=?(Parent)session.load(Parent.class,new Integer(7));

    運行提示出錯,"can't get Entity.."

    知道是什么低級錯誤么?? 其實很弱智的東西,但是不注意還就會出現,呵呵,答案如下:


    posted @ 2006-11-07 19:28 Alex 閱讀(1650) | 評論 (3)編輯 收藏

    key words: mysql,外鍵,fm150

    這次在mysql中建立外鍵關聯時發現問題:
    alter?table?CHILD?add?constraint?FK3D1FCFC74B18345?foreign?key?(PARENTID)?references?PARENT; ?? ??


    提示..fm150錯誤,最后發現是mysql的版本問題,我用的是4.1的,對外鍵不知道是不支持還是支持的有問題,下載5.0的解決.
    posted @ 2006-11-07 09:44 Alex 閱讀(438) | 評論 (0)編輯 收藏

         摘要: 什么玩意  閱讀全文
    posted @ 2006-11-06 12:00 Alex 閱讀(3452) | 評論 (9)編輯 收藏

         摘要:   閱讀全文
    posted @ 2006-10-31 12:32 Alex 閱讀(8508) | 評論 (7)編輯 收藏

    訪問控制背景

    ??? 訪問控制技術是由美國國防部(Department of Defense, DoD)資助的研究和開發成果演變而來的。這一研究導致兩種基本類型訪問控制的產生:自主訪問控制(Discretionary Access Control, DAC)和強制訪問控制(Mandatory Access Control, MAC)。最初的研究和應用主要是為了防止機密信息被未經授權者訪問,近期的應用主要是把這些策略應用到為商業領域。

    ??? 自主訪問控制,允許把訪問控制權的授予和取消留給個體用戶來判斷。為沒有訪問控制權的個體用戶授予和廢除許可。自主訪問控制機制允許用戶被授權和
    取 消訪問其控制之下的任何客體(object),換句話說,用戶就是他們控制下的客體的擁有者。然而,對于多數組織來說,最終用戶對所訪問的信息沒有擁有 權。對于這些組織,公司或代理機構是事實上的系統客體和處理他們的程序的擁有者。訪問優先權受組織控制,而且也常常基于雇員功能而不是數據所有權。

    ?? 強制訪問控制,在美國國防部 Trusted Computer Security Evaluation Criteria (TCSEC) 中定義如下:“一種限制訪問客體的手段,它以包含在這些客體中的信息敏感性和訪問這些敏感性信息的主體的正式授權信息(如清除)為基礎”。
    ??
    ?? 以上訪問控制策略對于處理一些無需保密但又敏感的信息的政府和行業組織的需求并不是特別的適合。在這樣的環境下,安全目標支持產生于現有法律、道德規范、 規章、或一般慣例的高端組織策略。這些環境通常需要控制個體行為的能力,而不僅僅是如何根據信息的敏感性為其設置標簽從而訪問這一信息的個人能力。
    ????


    什么是基于角色訪問控制(Role-Based Access Control, RBAC)?NIST 有如下定義。
    ??
    ?? 訪問是一種利用計算機資源去做某件事情的的能力,訪問控制是一種手段,通過它這種能力在某些情況下被允許或者受限制(通常是通過物理上和基于系統的控 制)?;谟嬎銠C的訪問控制不僅可規定是“誰”或某個操作有權使用特定系統資源,而且也能規定被允許的訪問類型。這些控制方式可在計算機系統或者外部設備 中實現。
    ??
    ??? 就基于角色訪問控制而言,訪問決策是基于角色的,個體用戶是某個組織的一部分。用戶具有指派的角色(比如醫生、護士、出納、經理)。定義角色的過程應該基于對組織運轉的徹底分析,應該包括來自一個組織中更廣范圍用戶的輸入。
    ???
    ??? 訪問權按角色名分組,資源的使用受限于授權給假定關聯角色的個體。例如,在一個醫院系統中,醫生角色可能包括進行診斷、開據處方、指示實驗室化驗等;而研究員的角色則被限制在收集用于研究的匿名臨床信息工作上。
    ???
    ??? 控制訪問角色的運用可能是一種開發和加強企業特殊安全策略,進行安全管理過程流程化的有效手段。
    ?????


    用戶(User)和角色(Role)

    ??? 用戶指訪問系統中的資源的主體,一般為人,也可為 Agent 等智能程序。角色指應用領域內一種權力和責任的語義綜合體,可以是一個抽象概念,也可以是對應于實際系統中的特定語義體,比如組織內部的職務等。針對角色 屬性的不同,某些模型中將角色進一步細分為普通角色和管理員角色(可理解為全局角色)。

    ?

    許可(Permissions)和權限(Permission)

    ??? 許可描述了角色對計算機資源的訪問和操作所具有的權限,其反映的是授權的結果。比如授予某個角色對計算機資源有讀的權限,則代表了一個許可的存在,這個許 可表示:角色獲取了對計算機資源的讀許可。針對操作來說,其描述的是許可和操作之間的一種關聯關系,而這層關系則表示了某一角色對某一操作所具有的權限及 權限狀態。


    ?????
    角色和指派(Assignment)

    ??? 指派包含兩個方面,用戶指派和許可指派。用戶指派表示的是,將用戶指派給特定的角色。許可指派表示的是為角色指派計算機資源的訪問和操作許可。

    ?

    會話(session)

    ??? 會話表示的是用戶和角色之間的關系。用戶每次必須通過建立會話來激活角色,得到相應的訪問權限。

    ?

    角色和角色等級(Role Hierarchies)

    ??? 角色本身僅僅只是一個名詞,其本身并不能代表權限的大小。比如,我們可以定一個“Director”的角色,也可以定一個“Project Leader”的角色。對于現實中我們來說,看到這樣兩個角色,就清楚 DIR 的權限要比一個 PL 的權限級別高。但是對計算機來說,這兩個角色僅僅是兩個“詞語”,是等同的??梢圆捎梅值燃壗巧?,在角色上實現層次化來解決這些問題。也可以采用復合角色 (其表示的就是一個角色組的概念),對角色實現一定的分組和復合,以便于權限指派。在一些 OA 產品中經常出現分等級角色。
    ???


    限制(Constraints)
    ???
    ??? 模型中的職責分離關系(Separation of Duty),用于控制沖突(Conflict)。靜態職責分離(Static SD)指定角色的互斥關系,用于用戶指派階段。避免同一用戶擁有互斥的角色。實現簡單,角色互斥語義關系清楚,便于管理不夠靈活,不能處理某些實際情況。 動態職責分離(Dynamic SD)指定角色的互斥關系,用于角色激活階段。允許同一用戶擁有某些互斥的角色,但是不允許該用戶同時激活互斥的角色。更靈活,直接與會話掛鉤,適應實際 管理需要,實現復雜,不易管理。

    ?????????????

    ?

    ?

    參考文獻

    《AN INTRODUCTION TO ROLE-BASED ACCESS CONTROL》 NIST

    《工作流授權控制模型》??????? 胡長城

    《基于角色的權限管理綜述》 俞詩鵬

    ?

    ?

    最后,感謝宏云博士對本文翻譯提供的指導。???


    請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處:http://www.tkk7.com/rosen

    posted @ 2006-10-26 21:31 Alex 閱讀(483) | 評論 (0)編輯 收藏

         摘要: 前言 : 權限往往是一個極其復雜的問題,但也可簡單表述為這樣的邏輯表達式:判斷“ Who 對 What(Which) ...  閱讀全文
    posted @ 2006-10-26 21:28 Alex 閱讀(369) | 評論 (0)編輯 收藏

    轉自 javaEye


    很多人對二級緩存都不太了解,或者是有錯誤的認識,我一直想寫一篇文章介紹一下hibernate的二級緩存的,今天終于忍不住了。
    我的經驗主要來自hibernate2.1版本,基本原理和3.0、3.1是一樣的,請原諒我的頑固不化。

    hibernate的session提供了一級緩存,每個session,對同一個id進行兩次load,不會發送兩條sql給數據庫,但是session關閉的時候,一級緩存就失效了。

    二級緩存是SessionFactory級別的全局緩存,它底下可以使用不同的緩存類庫,比如ehcache、oscache等,需要設置hibernate.cache.provider_class,我們這里用ehcache,在2.1中就是
    hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
    如果使用查詢緩存,加上
    hibernate.cache.use_query_cache=true

    緩存可以簡單的看成一個Map,通過key在緩存里面找value。

    Class的緩存
    對于一條記錄,也就是一個PO來說,是根據ID來找的,緩存的key就是ID,value是POJO。無論list,load還是 iterate,只要讀出一個對象,都會填充緩存。但是list不會使用緩存,而iterate會先取數據庫select id出來,然后一個id一個id的load,如果在緩存里面有,就從緩存取,沒有的話就去數據庫load。假設是讀寫緩存,需要設置:
    <cache usage="read-write"/>
    如果你使用的二級緩存實現是ehcache的話,需要配置ehcache.xml
    <cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" />
    其中eternal表示緩存是不是永遠不超時,timeToLiveSeconds是緩存中每個元素(這里也就是一個POJO)的超時時間,如 果eternal="false",超過指定的時間,這個元素就被移走了。timeToIdleSeconds是發呆時間,是可選的。當往緩存里面put 的元素超過500個時,如果overflowToDisk="true",就會把緩存中的部分數據保存在硬盤上的臨時文件里面。
    每個需要緩存的class都要這樣配置。如果你沒有配置,hibernate會在啟動的時候警告你,然后使用defaultCache的配置,這樣多個class會共享一個配置。
    當某個ID通過hibernate修改時,hibernate會知道,于是移除緩存。
    這樣大家可能會想,同樣的查詢條件,第一次先list,第二次再iterate,就可以使用到緩存了。實際上這是很難的,因為你無法判斷什么時候 是第一次,而且每次查詢的條件通常是不一樣的,假如數據庫里面有100條記錄,id從1到100,第一次list的時候出了前50個id,第二次 iterate的時候卻查詢到30至70號id,那么30-50是從緩存里面取的,51到70是從數據庫取的,共發送1+20條sql。所以我一直認為 iterate沒有什么用,總是會有1+N的問題。
    (題外話:有說法說大型查詢用list會把整個結果集裝入內存,很慢,而iterate只select id比較好,但是大型查詢總是要分頁查的,誰也不會真的把整個結果集裝進來,假如一頁20條的話,iterate共需要執行21條語句,list雖然選擇 若干字段,比iterate第一條select id語句慢一些,但只有一條語句,不裝入整個結果集hibernate還會根據數據庫方言做優化,比如使用mysql的limit,整體看來應該還是 list快。)
    如果想要對list或者iterate查詢的結果緩存,就要用到查詢緩存了

    查詢緩存
    首先需要配置hibernate.cache.use_query_cache=true
    如果用ehcache,配置ehcache.xml,注意hibernate3.0以后不是net.sf的包名了
    <cache name="net.sf.hibernate.cache.StandardQueryCache"
    maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
    timeToLiveSeconds="7200" overflowToDisk="true"/>
    <cache name="net.sf.hibernate.cache.UpdateTimestampsCache"
    maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
    然后
    query.setCacheable(true);//激活查詢緩存
    query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion,可選
    第二行指定要使用的cacheRegion是myCacheRegion,即你可以給每個查詢緩存做一個單獨的配置,使用setCacheRegion來做這個指定,需要在ehcache.xml里面配置它:
    <cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" />
    如果省略第二行,不設置cacheRegion的話,那么會使用上面提到的標準查詢緩存的配置,也就是net.sf.hibernate.cache.StandardQueryCache

    對于查詢緩存來說,緩存的key是根據hql生成的sql,再加上參數,分頁等信息(可以通過日志輸出看到,不過它的輸出不是很可讀,最好改一下它的代碼)。
    比如hql:
    from Cat c where c.name like ?
    生成大致如下的sql:
    select * from cat c where c.name like ?
    參數是"tiger%",那么查詢緩存的key*大約*是這樣的字符串(我是憑記憶寫的,并不精確,不過看了也該明白了):
    select * from cat c where c.name like ? , parameter:tiger%
    這樣,保證了同樣的查詢、同樣的參數等條件下具有一樣的key。
    現在說說緩存的value,如果是list方式的話,value在這里并不是整個結果集,而是查詢出來的這一串ID。也就是說,不管是list方 法還是iterate方法,第一次查詢的時候,它們的查詢方式很它們平時的方式是一樣的,list執行一條sql,iterate執行1+N條,多出來的 行為是它們填充了緩存。但是到同樣條件第二次查詢的時候,就都和iterate的行為一樣了,根據緩存的key去緩存里面查到了value,value是 一串id,然后在到class的緩存里面去一個一個的load出來。這樣做是為了節約內存。
    可以看出來,查詢緩存需要打開相關類的class緩存。list和iterate方法第一次執行的時候,都是既填充查詢緩存又填充class緩存的。
    這里還有一個很容易被忽視的重要問題,即打開查詢緩存以后,即使是list方法也可能遇到1+N的問題!相同條件第一次list的 時候,因為查詢緩存中找不到,不管class緩存是否存在數據,總是發送一條sql語句到數據庫獲取全部數據,然后填充查詢緩存和class緩存。但是第 二次執行的時候,問題就來了,如果你的class緩存的超時時間比較短,現在class緩存都超時了,但是查詢緩存還在,那么list方法在獲取id串以 后,將會一個一個去數據庫load!因此,class緩存的超時時間一定不能短于查詢緩存設置的超時時間!如果還設置了發呆時間的話,保證class緩存 的發呆時間也大于查詢的緩存的生存時間。這里還有其他情況,比如class緩存被程序強制evict了,這種情況就請自己注意了。

    另外,如果hql查詢包含select字句,那么查詢緩存里面的value就是整個結果集了。

    當hibernate更新數據庫的時候,它怎么知道更新哪些查詢緩存呢?
    hibernate在一個地方維護每個表的最后更新時間,其實也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的緩存配置里面。
    當通過hibernate更新的時候,hibernate會知道這次更新影響了哪些表。然后它更新這些表的最后更新時間。每個緩存都有一個生成時 間和這個緩存所查詢的表,當hibernate查詢一個緩存是否存在的時候,如果緩存存在,它還要取出緩存的生成時間和這個緩存所查詢的表,然后去查找這 些表的最后更新時間,如果有一個表在生成時間后更新過了,那么這個緩存是無效的。
    可以看出,只要更新過一個表,那么凡是涉及到這個表的查詢緩存就失效了,因此查詢緩存的命中率可能會比較低。

    Collection緩存
    需要在hbm的collection里面設置
    <cache usage="read-write"/>
    假如class是Cat,collection叫children,那么ehcache里面配置
    <cache name="com.xxx.pojo.Cat.children"
    maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
    overflowToDisk="true" />
    Collection的緩存和前面查詢緩存的list一樣,也是只保持一串id,但它不會因為這個表更新過就失效,一個collection緩存僅在這個collection里面的元素有增刪時才失效。
    這樣有一個問題,如果你的collection是根據某個字段排序的,當其中一個元素更新了該字段時,導致順序改變時,collection緩存里面的順序沒有做更新。

    緩存策略
    只讀緩存(read-only):沒有什么好說的
    讀/寫緩存(read-write):程序可能要的更新數據
    不嚴格的讀/寫緩存(nonstrict-read-write):需要更新數據,但是兩個事務更新同一條記錄的可能性很小,性能比讀寫緩存好
    事務緩存(transactional):緩存支持事務,發生異常的時候,緩存也能夠回滾,只支持jta環境,這個我沒有怎么研究過

    讀寫緩存和不嚴格讀寫緩存在實現上的區別在于,讀寫緩存更新緩存的時候會把緩存里面的數據換成一個鎖,其他事務如果去取相應的緩存數據,發現被鎖住了,然后就直接取數據庫查詢。
    在hibernate2.1的ehcache實現中,如果鎖住部分緩存的事務發生了異常,那么緩存會一直被鎖住,直到60秒后超時。
    不嚴格讀寫緩存不鎖定緩存中的數據。

    使用二級緩存的前置條件
    你的hibernate程序對數據庫有獨占的寫訪問權,其他的進程更新了數據庫,hibernate是不可能知道的。你操作數據庫必需直接通過 hibernate,如果你調用存儲過程,或者自己使用jdbc更新數據庫,hibernate也是不知道的。hibernate3.0的大批量更新和刪 除是不更新二級緩存的,但是據說3.1已經解決了這個問題。
    這個限制相當的棘手,有時候hibernate做批量更新、刪除很慢,但是你卻不能自己寫jdbc來優化,很郁悶吧。
    SessionFactory也提供了移除緩存的方法,你一定要自己寫一些JDBC的話,可以調用這些方法移除緩存,這些方法是:
    void evict(Class persistentClass)
    Evict all entries from the second-level cache.
    void evict(Class persistentClass, Serializable id)
    Evict an entry from the second-level cache.
    void evictCollection(String roleName)
    Evict all entries from the second-level cache.
    void evictCollection(String roleName, Serializable id)
    Evict an entry from the second-level cache.
    void evictQueries()
    Evict any query result sets cached in the default query cache region.
    void evictQueries(String cacheRegion)
    Evict any query result sets cached in the named query cache region.
    不過我不建議這樣做,因為這樣很難維護。比如你現在用JDBC批量更新了某個表,有3個查詢緩存會用到這個表,用evictQueries (String cacheRegion)移除了3個查詢緩存,然后用evict(Class persistentClass)移除了class緩存,看上去好像完整了。不過哪天你添加了一個相關查詢緩存,可能會忘記更新這里的移除代碼。如果你的 jdbc代碼到處都是,在你添加一個查詢緩存的時候,還知道其他什么地方也要做相應的改動嗎?

    ----------------------------------------------------

    總結:
    不要想當然的以為緩存一定能提高性能,僅僅在你能夠駕馭它并且條件合適的情況下才是這樣的。hibernate的二級緩存限制還是比較多的,不方便用jdbc可能會大大的降低更新性能。在不了解原理的情況下亂用,可能會有1+N的問題。不當的使用還可能導致讀出臟數據。
    如果受不了hibernate的諸多限制,那么還是自己在應用程序的層面上做緩存吧。
    在越高的層面上做緩存,效果就會越好。就好像盡管磁盤有緩存,數據庫還是要實現自己的緩存,盡管數據庫有緩存,咱們的應用程序還是要做緩存。因為 底層的緩存它并不知道高層要用這些數據干什么,只能做的比較通用,而高層可以有針對性的實現緩存,所以在更高的級別上做緩存,效果也要好些吧。

    終于寫完了,好累……

    posted @ 2006-10-23 14:30 Alex 閱讀(624) | 評論 (1)編輯 收藏

    在Struts或別的框架中集成Spring的時候,Spring向我們提供了獲得context的方法 getApplicationContext,那在jsp中如何獲得呢?

    ApplicationContext?ctx?=?WebApplicationContextUtils.getRequiredWebApplicationContext
    (
    this.getServletConfig().getServletContext());

    建議在項目中開發的時候提供一個singleton對外公布統一的applicationContext,畢竟不是每個人都一定能獲得web環境或servlet.

    posted @ 2006-10-23 11:03 Alex 閱讀(2533) | 評論 (0)編輯 收藏

    僅列出標題
    共15頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
    主站蜘蛛池模板: 永久免费视频网站在线观看| 亚洲女子高潮不断爆白浆| kk4kk免费视频毛片| 国产黄色片在线免费观看| 亚洲中文字幕乱码一区| 成人黄页网站免费观看大全| 亚洲一卡2卡3卡4卡5卡6卡| 免费人成视频在线| 久久久久亚洲精品无码网址色欲| 国产伦精品一区二区三区免费下载 | 亚洲视频免费在线播放| 亚洲人成综合在线播放| 卡1卡2卡3卡4卡5免费视频| 美国免费高清一级毛片| 国产亚洲美女精品久久久2020| 在线毛片片免费观看| 亚洲成a人片在线观| 免费高清资源黄网站在线观看| 亚洲第一街区偷拍街拍| 国产亚洲色视频在线| 最好看最新的中文字幕免费| 亚洲一区二区三区成人网站| 免费一级毛片不卡不收费| a毛片免费播放全部完整| 亚洲中字慕日产2020| 亚洲AV无码乱码在线观看性色扶| 精品熟女少妇aⅴ免费久久| 亚洲第一永久在线观看| 日本一区二区三区日本免费| 日韩电影免费在线观看网站 | 亚洲一本一道一区二区三区| 亚洲福利视频一区二区| 91香蕉国产线观看免费全集| 午夜亚洲国产理论片二级港台二级 | 日本在线看片免费人成视频1000| 亚洲人成人网毛片在线播放| 亚洲福利精品一区二区三区| 麻豆高清免费国产一区| 一个人免费观看视频在线中文| 亚洲最大在线视频| 亚洲精品第一国产综合精品99|