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

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

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

    少年阿賓

    那些青春的歲月

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

    #

    REST是一種架構風格,其核心是面向資源,REST專門針對網絡應用設計和開發方式,以降低開發的復雜性,提高系統的可伸縮性。REST提出設計概念和準則為:

    1.網絡上的所有事物都可以被抽象為資源(resource)

    2.每一個資源都有唯一的資源標識(resource identifier),對資源的操作不會改變這些標識

    3.所有的操作都是無狀態的

    REST簡化開發,其架構遵循CRUD原則,該原則告訴我們對于資源(包括網絡資源)只需要四種行為:創建,獲取,更新和刪除就可以完成相關的操作和處理。您可以通過統一資源標識符(Universal Resource Identifier,URI)來識別和定位資源,并且針對這些資源而執行的操作是通過 HTTP 規范定義的。其核心操作只有GET,PUT,POST,DELETE。

    由于REST強制所有的操作都必須是stateless的,這就沒有上下文的約束,如果做分布式,集群都不需要考慮上下文和會話保持的問題。極大的提高系統的可伸縮性。

    對于SOAP Webservice和Restful Webservice的選擇問題,首先需要理解就是SOAP偏向于面向活動,有嚴格的規范和標準,包括安全,事務等各個方面的內容,同時SOAP強調操作方法和操作對象的分離,有WSDL文件規范和XSD文件分別對其定義。而REST強調面向資源,只要我們要操作的對象可以抽象為資源即可以使用REST架構風格。

    如果從這個意義上講,是否使用REST就需要考慮資源本身的抽象和識別是否困難,如果本身就是簡單的類似增刪改查的業務操作,那么抽象資源就比較容易,而對于復雜的業務活動抽象資源并不是一個簡單的事情。比如校驗用戶等級,轉賬,事務處理等,這些往往并不容易簡單的抽象為資源。

    其次如果有嚴格的規范和標準定義要求,而且前期規范標準需要指導多個業務系統集成和開發的時候,SOAP風格由于有清晰的規范標準定義是明顯有優勢的。我們可以在開始和實現之前就嚴格定義相關的接口方法和接口傳輸數據。

    簡單數據操作,無事務處理,開發和調用簡單這些是使用REST架構風格的優勢。而對于較為復雜的面向活動的服務,如果我們還是使用REST,很多時候都是仍然是傳統的面向活動的思想通過轉換工具再轉換得到REST服務,這種使用方式是沒有意義的。

    正如另外一篇文章里面談到的,REST核心是url和面向資源,url代替了原來復雜的操作方法。REST允許我們通過url設計系統,就像測試驅動開發使用測試用例設計類接口一樣。所有可以被抽象為資源的東西都可以使用RESTful的url,當我們以傳統的用SOAP方式實現的一個查詢訂單服務的時候可以看到,這個服務首先存在輸入的查詢條件,然后才是輸出結果集。那么對于類似場景要使用REST,不可避免的會將傳統的SOAP服務拆分為一個HTTP POST操作和一個HTTP GET操作。前面是輸入,而后面是輸出。

    使用REST的關鍵是如何抽象資源,抽象的越精確,對REST的應用越好。如何進行抽象,面向資源的設計和傳統的面向結構和對象設計區別,資源和對象,數據庫表之間的差別是另外一個在分析設計時候要考慮的問題。在REST分析設計中如何改變傳統的SOAP分析設計思想又是一個重要問題。

    下文轉載自:http://hi.baidu.com/gaohong230/blog/item/cd3924396bc7332fb9998f52.html

    在SOA的基礎技術實現方式中WebService占據了很重要的地位,通常我們提到WebService第一想法就是SOAP消息在各種傳輸協議上交互。近幾年REST的思想伴隨著SOA逐漸被大家接受,同時各大網站不斷開放API提供給開發者,也激起了REST風格WebService的熱潮。

    SOAP

    什么是SOAP,我想不用多說,google一把滿眼都是。其實SOAP最早是針對RPC的一種解決方案,簡單對象訪問協議,很輕量,同時作為應用協議可以基于多種傳輸協議來傳遞消息(Http,SMTP等)。但是隨著SOAP作為WebService的廣泛應用,不斷地增加附加的內容,使得現在開發人員覺得SOAP很重,使用門檻很高。在SOAP后續的發展過程中,WS-*一系列協議的制定,增加了SOAP的成熟度,也給SOAP增加了負擔。

    REST

    REST其實并不是什么協議也不是什么標準,而是將Http協議的設計初衷作了詮釋,在Http協議被廣泛利用的今天,越來越多的是將其作為傳輸協議,而非原先設計者所考慮的應用協議。SOAP類型的WebService就是最好的例子,SOAP消息完全就是將Http協議作為消息承載,以至于對于Http協議中的各種參數(例如編碼,錯誤碼等)都置之不顧。其實,最輕量級的應用協議就是Http協議。Http協議所抽象的get,post,put,delete就好比數據庫中最基本的增刪改查,而互聯網上的各種資源就好比數據庫中的記錄(可能這么比喻不是很好),對于各種資源的操作最后總是能抽象成為這四種基本操作,在定義了定位資源的規則以后,對于資源的操作通過標準的Http協議就可以實現,開發者也會受益于這種輕量級的協議。

    REST的思想歸結以下有如下幾個關鍵點:

    1.面向資源的接口設計

    所有的接口設計都是針對資源來設計的,也就很類似于我們的面向對象和面向過程的設計區別,只不過現在將網絡上的操作實體都作為資源來看待,同時URI的設計也是體現了對于資源的定位設計。后面會提到有一些網站的API設計說是REST設計,其實是RPC-REST的混合體,并非是REST的思想。

    2.抽象操作為基礎的CRUD

    這點很簡單,Http中的get,put,post,delete分別對應了read,update,create,delete四種操作,如果僅僅是作為對于資源的操作,抽象成為這四種已經足夠了,但是對于現在的一些復雜的業務服務接口設計,可能這樣的抽象未必能夠滿足。其實這也在后面的幾個網站的API設計中暴露了這樣的問題,如果要完全按照REST的思想來設計,那么適用的環境將會有限制,而非放之四海皆準的。

    3.Http是應用協議而非傳輸協議

    這點在后面各大網站的API分析中有很明顯的體現,其實有些網站已經走到了SOAP的老路上,說是REST的理念設計,其實是作了一套私有的SOAP協議,因此稱之為REST風格的自定義SOAP協議。

    4.無狀態,自包含

    這點其實不僅僅是對于REST來說的,作為接口設計都需要能夠做到這點,也是作為可擴展和高效性的最基本的保證,就算是使用SOAP的WebService也是一樣。

    SOAP Webservice和RESTful Webservice的比較

    成熟度(總的來說SOAP在成熟度上優于REST)

    SOAP雖然發展到現在已經脫離了初衷,但是對于異構環境服務發布和調用,以及廠商的支持都已經達到了較為成熟的情況。不同平臺,開發語言之間通過SOAP來交互的web service都能夠較好的互通(在部分復雜和特殊的參數和返回對象解析上,協議沒有作很細致的規定,導致還是需要作部分修正)

    REST國外很多大網站都發布了自己的開發API,很多都提供了SOAP和REST兩種Web Service,根據調查部分網站的REST風格的使用情況要高于SOAP。但是由于REST只是一種基于Http協議實現資源操作的思想,因此各個網站的REST實現都自有一套,在后面會講訴各個大網站的REST API的風格。也正是因為這種各自實現的情況,在性能和可用性上會大大高于SOAP發布的web service,但統一通用方面遠遠不及SOAP。由于這些大網站的SP往往專注于此網站的API開發,因此通用性要求不高。

    由于沒有類似于SOAP的權威性協議作為規范,REST實現的各種協議僅僅只能算是私有協議,當然需要遵循REST的思想,但是這樣細節方面有太多沒有約束的地方。REST日后的發展所走向規范也會直接影響到這部分的設計是否能夠有很好的生命力。

    效率和易用性(REST更勝一籌)

    SOAP協議對于消息體和消息頭都有定義,同時消息頭的可擴展性為各種互聯網的標準提供了擴展的基礎,WS-*系列就是較為成功的規范。但是也由于SOAP由于各種需求不斷擴充其本身協議的內容,導致在SOAP處理方面的性能有所下降。同時在易用性方面以及學習成本上也有所增加。

    REST被人們的重視,其實很大一方面也是因為其高效以及簡潔易用的特性。這種高效一方面源于其面向資源接口設計以及操作抽象簡化了開發者的不良設計,同時也最大限度的利用了Http最初的應用協議設計理念。同時,在我看來REST還有一個很吸引開發者的就是能夠很好的融合當前Web2.0的很多前端技術來提高開發效率。例如很多大型網站開放的REST風格的API都會有多種返回形式,除了傳統的xml作為數據承載,還有(JSON,RSS,ATOM)等形式,這對很多網站前端開發人員來說就能夠很好的mashup各種資源信息。

    安全性:

    這點其實可以放入到成熟度中,不過在當前的互聯網應用和平臺開發設計過程中,安全已經被提到了很高的高度,特別是作為外部接口給第三方調用,安全性可能會高過業務邏輯本身。

    SOAP在安全方面是通過使用XML-Security和XML-Signature兩個規范組成了WS-Security來實現安全控制的,當前已經得到了各個廠商的支持,.net ,php ,java 都已經對其有了很好的支持(雖然在一些細節上還是有不兼容的問題,但是互通基本上是可以的)。

    REST沒有任何規范對于安全方面作說明,同時現在開放REST風格API的網站主要分成兩種,一種是自定義了安全信息封裝在消息中(其實這和SOAP沒有什么區別),另外一種就是靠硬件SSL來保障,但是這只能夠保證點到點的安全,如果是需要多點傳輸的話SSL就無能為力了。安全這塊其實也是一個很大的問題,今年在BEA峰會上看到有演示采用SAML2實現的網站間SSO,其實是直接采用了XML-Security和XML-Signature,效率看起來也不是很高。未來REST規范化和通用化過程中的安全是否也會采用這兩種規范,是未知的,但是加入的越多,REST失去它高效性的優勢越多。

    應用設計與改造:

    我們的系統要么就是已經有了那些需要被發布出去的服務,要么就是剛剛設計好的服務,但是開發人員的傳統設計思想讓REST的形式被接受還需要一點時間。同時在資源型數據服務接口設計上來說按照REST的思想來設計相對來說要容易一些,而對于一些復雜的服務接口來說,可能強要去按照REST的風格來設計會有些牽強。這一點其實可以看看各大網站的接口就可以知道,很多網站還要傳入function的名稱作為參數,這就明顯已經違背了REST本身的設計思路。而SOAP本身就是面向RPC來設計的,開發人員十分容易接受,所以不存在什么適應的過程。總的來說,其實還是一個老觀念,適合的才是最好的

    技術沒有好壞,只有是不是合適,一種好的技術和思想被誤用了,那么就會得到反效果。REST和SOAP各自都有自己的優點,同時如果在一些場景下如果去改造REST,其實就會走向SOAP(例如安全)。

    REST對于資源型服務接口來說很合適,同時特別適合對于效率要求很高,但是對于安全要求不高的場景。而SOAP的成熟性可以給需要提供給多開發語言的,對于安全性要求較高的接口設計帶來便利。所以我覺得純粹說什么設計模式將會占據主導地位沒有什么意義,關鍵還是看應用場景。

    同時很重要一點就是不要扭曲了REST現在很多網站都跟風去開發REST風格的接口,其實都是在學其形,不知其心,最后弄得不倫不類,性能上不去,安全又保證不了,徒有一個看似象摸象樣的皮囊。

    posted @ 2012-05-24 14:55 abin 閱讀(605) | 評論 (0)編輯 收藏

    進程和程序區別和聯系表現在以下方面:
    1)程序只是一組指令的有序集合,它本身沒有任何運行的含義,它只是
     一個靜態的實體。而進程則不同,它是程序在某個數據集上的執行。
     進程是一個動態的實體,它有自己的生命周期。它因創建而產生,因
     調度而運行,因等待資源或事件而被處于等待狀態,因完成任務而被
     撤消。反映了一個程序在一定的數據集上運行的全部動態過程。
    2)進程和程序并不是一一對應的,一個程序執行在不同的數據集上就成
     為不同的進程,可以用進程控制塊來唯一地標識每個進程。而這一點
     正是程序無法做到的,由于程序沒有和數據產生直接的聯系,既使是
     執行不同的數據的程序,他們的指令的集合依然是一樣的,所以無法
     唯一地標識出這些運行于不同數據集上的程序。一般來說,一個進程
     肯定有一個與之對應的程序,而且只有一個。而一個程序有可能沒有
     與之對應的進程(因為它沒有執行),也有可能有多個進程與之對應(運
     行在幾個不同的數據集上)。
    3)進程還具有并發性和交往性,這也與程序的封閉性不同。
    ----------------------------------------------------------------------------------------------
    
    進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的并發性。進程和線程的區別在于:
    
    簡而言之,一個程序至少有一個進程,一個進程至少有一個線程. 
    線程的劃分尺度小于進程,使得多線程程序的并發性高。
    另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
    線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
    從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
    
    進程是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
    線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
    一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以并發執行.
    
    ----------------------------------------------------------------------------------------------
    
    進程和線程的區別 
     
    說法一:進程是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
    
    線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
    
    一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以并發執行
    
     
    
    說法二:進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的并發性。進程和線程的區別在于:
    
    簡而言之,一個程序至少有一個進程,一個進程至少有一個線程. 
    
    線程的劃分尺度小于進程,使得多線程程序的并發性高。
    
    另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
    
    線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
    
    從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
    
     
    
    說法三:多線程共存于應用程序中是現代操作系統中的基本特征和重要標志。用過UNIX操作系統的讀者知道進程,在UNIX操作系統中,每個應用程序的執行都在操作系統內核中登記一個進程標志,操作系統根據分配的標志對應用程序的執行進行調度和系統資源分配,但進程和線程有什么區別呢?
    
    進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的并發性。進程和線程的區別在于:
    
    線程的劃分尺度小于進程,使得多線程程序的并發性搞。
    
    另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
    
    線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
    
    從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
    
    進程(Process)是最初定義在Unix等多用戶、多任務操作系統環境下用于表示應用程序在內存環境中基本執行單元的概念。以Unix操作系統為例,進程是Unix操作系統環境中的基本成分、是系統資源分配的基本單位。Unix操作系統中完成的幾乎所有用戶管理和資源分配等工作都是通過操作系統對應用程序進程的控制來實現的。 
    
    C、C++、Java等語言編寫的源程序經相應的編譯器編譯成可執行文件后,提交給計算機處理器運行。這時,處在可執行狀態中的應用程序稱為進程。從用戶角度來看,進程是應用程序的一個執行過程。從操作系統核心角度來看,進程代表的是操作系統分配的內存、CPU時間片等資源的基本單位,是為正在運行的程序提供的運行環境。進程與應用程序的區別在于應用程序作為一個靜態文件存儲在計算機系統的硬盤等存儲空間中,而進程則是處于動態條件下由操作系統維護的系統資源管理實體。多任務環境下應用程序進程的主要特點包括: 
    
    ●進程在執行過程中有內存單元的初始入口點,并且進程存活過程中始終擁有獨立的內存地址空間; 
    
    ●進程的生存期狀態包括創建、就緒、運行、阻塞和死亡等類型; 
    
    ●從應用程序進程在執行過程中向CPU發出的運行指令形式不同,可以將進程的狀態分為用戶態和核心態。處于用戶態下的進程執行的是應用程序指令、處于核心態下的應用程序進程執行的是操作系統指令。 
    
    在Unix操作系統啟動過程中,系統自動創建swapper、init等系統進程,用于管理內存資源以及對用戶進程進行調度等。在Unix環境下無論是由操作系統創建的進程還要由應用程序執行創建的進程,均擁有唯一的進程標識(PID)。 
    
    說法四:應用程序在執行過程中存在一個內存空間的初始入口點地址、一個程序執行過程中的代碼執行序列以及用于標識進程結束的內存出口點地址,在進程執行過程中的每一時間點均有唯一的處理器指令與內存單元地址相對應。 
    
    Java語言中定義的線程(Thread)同樣包括一個內存入口點地址、一個出口點地址以及能夠順序執行的代碼序列。但是進程與線程的重要區別在于線程不能夠單獨執行,它必須運行在處于活動狀態的應用程序進程中,因此可以定義線程是程序內部的具有并發性的順序代碼流。 
    
    Unix操作系統和Microsoft Windows操作系統支持多用戶、多進程的并發執行,而Java語言支持應用程序進程內部的多個執行線程的并發執行。多線程的意義在于一個應用程序的多個邏輯單元可以并發地執行。但是多線程并不意味著多個用戶進程在執行,操作系統也不把每個線程作為獨立的進程來分配獨立的系統資源。進程可以創建其子進程,子進程與父進程擁有不同的可執行代碼和數據內存空間。而在用于代表應用程序的進程中多個線程共享數據內存空間,但保持每個線程擁有獨立的執行堆棧和程序執行上下文(Context)。 
    
    基于上述區別,線程也可以稱為輕型進程 (Light Weight Process,LWP)。不同線程間允許任務協作和數據交換,使得在計算機系統資源消耗等方面非常廉價。 
    
    線程需要操作系統的支持,不是所有類型的計算機都支持多線程應用程序。Java程序設計語言將線程支持與語言運行環境結合在一起,提供了多任務并發執行的能力。這就好比一個人在處理家務的過程中,將衣服放到洗衣機中自動洗滌后將大米放在電飯鍋里,然后開始做菜。等菜做好了,飯熟了同時衣服也洗好了。 
    
    需要注意的是:在應用程序中使用多線程不會增加 CPU 的數據處理能力。只有在多CPU 的計算機或者在網絡計算體系結構下,將Java程序劃分為多個并發執行線程后,同時啟動多個線程運行,使不同的線程運行在基于不同處理器的Java虛擬機中,才能提高應用程序的執行效率。 
    posted @ 2012-05-22 15:19 abin 閱讀(2322) | 評論 (0)編輯 收藏

    百度移動終端研發工程師

    1.寫一個字符串逆序的程序,時間復雜度和空間復雜度最低,效率越高越好。

    2.實質:二叉樹的層序遍歷,每層的結點用單鏈表輸出。

    3.1-N(N最大32000,且未知),內存只有4K,找出其中的重復數

    4.編程題,比較復雜,是個系統設計題,與《編程之美》中3.2,電話號碼對應英語單詞類似。

    百度軟件開發工程師

    1.有101個數,為[1,100]之間的數,其中一個數是重復的,如何尋找這個重復的數,其時間復雜度和空間復雜度是多少?

    2.Java中抽象類與接口的區別。

    3.進程與線程之間的聯系與區別。(多家公司都在問,好好研究一下)

    4.談談對設計模式的認識與理解,簡單介紹一下你所知道的設計模式。(多家公司都問,Android方向面試必考的)

    5.線程、多線程相關(必問)

    6.Linux常用的命令,shell編程,grep命令的使用。

    7.海量數據查找或者排序,有資源限制要求。(常考的)

    Sina無線客戶端開發工程師

    筆試的題目和7月22日實習生的題目差不多。面試主要問了:

    1.二叉樹的一些基礎知識。

    2.Java多線程,對stop()方法的認識,如何安全的終止一個線程。

    3.設計模式相關的問題

    4.談談你對面向對象編程中繼承的認識

    5.排序算法

    網易2012校招無線客戶端開發

    1.面向對象編程中多態的概念,用偽代碼展示出來。

    2.斐波那契數列編程,效率越高越好(詳見《編程之美》2.9)

    3.60W長度為32的字符串一次性讀入內存中,大約占用多少內存空間?

    4.一個X向量n,如何求其內部的最大距離。

    5.在瀏覽器中輸入http://www.163.com,從輸入到頁面在瀏覽器中顯示出來,期間發生了哪些過程,越詳細越好。

    6.簡單介紹一下Android系統中的Activity,Service, Intent, ContentProvider組件。

    7.編程解析一段josn格式內容,并在界面上顯示出來。

    8.英文閱讀,考察英語能力。

    9.網絡應用分析,發揮自己的主觀能動性和積累。

    搜狗

      搜狗的題目出的很全,所有職位的題目都在一份卷子上,涉及到數據結構、網絡、操作系統、算法、軟件工程等多方面,根據自己所投遞的職位,有針對性的選擇要答的題目即可。

    金山

      為了保險,做了運維的題目,難度不大,主要是網絡和Linux操作系統方面的,稍微準備一下即可。答題的時候自我感覺良好,結果沒收到面試通知,被鄙視了,o(╯□╰)o

    Android開發工程師

    1.Activity的生命周期(最基本的)

    2.Android基本框架結構。

    3.Android終止一個進程的方法,如何徹底終止一個程序。

    4.如何改寫程序,改變android手機中返回鍵的功能(西安TCL研究院技術面試)。


    posted @ 2012-05-22 15:05 abin 閱讀(548) | 評論 (0)編輯 收藏

    一、SQL刪除某些字段重復的記錄(只保留一條) 
    1.查詢出來重復的記錄數:
    select t.* from test2 t inner join(select name,age from test2 s group by name,age having count(*)>1)b
    on t.name=b.name and t.age=b.age

    select t.name,t.age,count(*) as num1 from test2 t group by name,age having count(*)>1
    2.刪除重復的記錄數(只保留一條):
    delete from test2 t where t.id not in (select max(id) from test2 s group by name,age)

    二、一個表中有一個id字段,選出重復大于三的字段:
    select id,count(name) from test t group by id having count(name)>=3

    兩個日期間的天數 :
    select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;
    posted @ 2012-05-22 14:42 abin 閱讀(407) | 評論 (0)編輯 收藏

    **
    * 使用hql 語句進行操作

       * @param hql
    * @param offset
    * @param length
    * @return List
    */
    public List getListForPage(final String hql, final int offset,
        final int length) {
       List list = getHibernateTemplate().executeFind(new HibernateCallback() {
        public Object doInHibernate(Session session)
          throws HibernateException, SQLException {
         Query query = session.createQuery(hql);
         query.setFirstResult(offset);
         query.setMaxResults(length);
         List list = query.list();
         return list;
        }
       });
       return list;
    }/**
    * 使用criterion進行操作
    * @param arg
    * @param criterions
    * @param offset
    * @param length
    * @return List
    */
    protected List getListForPage(final Class arg, final Criterion[] criterions,final int offset, final int length) {
       List list = getHibernateTemplate().executeFind(new HibernateCallback() {
        public Object doInHibernate(Session session)
          throws HibernateException, SQLException {
         Criteria criteria = session.createCriteria(arg);
         //循環遍歷添加約束條件
         for (int i = 0; i < criterions.length; i++) {
          criteria.add(criterions[i]);
         }
         criteria.setFirstResult(offset);
         criteria.setMaxResults(length);
         return criteria.list();
        }
       });
       return list;
    }

    你不是說你用HibernateTemplate了,如果你用的是spring的HibernateTemplate,那么就直接用就行了,如果你是自己寫的template,
    那你也應該會準備一個HibernateCallback類啊,這才是典型的模板加回調啊

    算了,把HibernateCallback也給你貼出來

    import org.hibernate.HibernateException;
    import org.hibernate.Session;

    /*************************************
    * 為 Hibernate 所提供的一個 回調接口,
    * 此接口定義了 統一 Hibernate的業務操作;
    * @author kenshin
    *
    */
    public interface HibernateCallback {

    /**************************************
      * 回調接口的回調方法,此方法使用者無需調用,
      * 它由 模板類來進行回調,并傳入一個 session參數,
      * 以便讓使用者完成相關業務
      * @param ses
      * @return 執行結果
      * @throws HibernateException
      */
    Object doInHibernate(Session ses)
           throws HibernateException;

    }
    posted @ 2012-05-17 16:54 abin 閱讀(570) | 評論 (0)編輯 收藏

    Cache簡介: 緩存(Cache )是計算機領域非常通用的概念。它介于應用程序和永久性數據存儲源(如硬盤上的文件或者數據庫)之間,其作用是降低應用程序直接讀寫永久性數據存儲源的頻率,從而提高應用的運行性能。緩存中的數據是數據存儲源中數據的拷貝,應用程序在運行時直接讀寫緩存中的數據,只在某些特定時刻按照緩存中的數據來同步更新數據存儲源。
    緩存的物理介質通常是內存,而永久性數據存儲源的物理介質通常是硬盤或磁盤,應用程序讀寫內在的速度顯然比讀寫硬盤的速度快,如果緩存中存放的數據量非常大,也會用硬盤作為緩存的物理介質。
    緩存的實現不僅需要作為物理介質的硬件,同時還需要用于管理緩存的并發訪問和過期等策略的軟件。因此,緩存是通過軟件和硬件共同實現的。
    1.1.    持久化層的緩存的范圍
    緩存的范圍決定了緩存的生命周期以及可以被誰訪問。緩存的范圍分為三類。
    1) 事務范圍:緩存只能被當前事務訪問。緩存的生命周期依賴于事務的生命周期,當事務結束時,緩存也就結束生命周期。在此范圍下,緩存的介質是內存。事務可以是數據庫事務或者應用事務,每個事務都有獨自的緩存,緩存內的數據通常采用相互關聯的對象形式。
    2) 進程范圍:緩存被進程內的所有事務共享。這些事務有可能是并發訪問緩存,因此必須對緩存采取必要的事務隔離機制。緩存的生命周期依賴于進程的生命周期,進程結束時,緩存也就結束了生命周期。進程范圍的緩存可能會存放大量的數據,所以存放的介質可以是內存或硬盤。緩存內的數據既可以是相互關聯的對象形式也可以是對象的松散數據形式。松散的對象數據形式有點類似于對象的序列化數據,但是對象分解為松散的算法比對象序列化的算法要求更快。
    3) 集群范圍:在集群環境中,緩存被一個機器或者多個機器的進程共享。緩存中的數據被復制到集群環境中的每個進程節點,進程間通過遠程通信來保證緩存中的數據的一致性,緩存中的數據通常采用對象的松散數據形式。
    對大多數應用來說,應該慎重地考慮是否需要使用集群范圍的緩存,因為訪問的速度不一定會比直接訪問數據庫數據的速度快多少。
    持久化層可以提供多種范圍的緩存。如果在事務范圍的緩存中沒有查到相應的數據,還可以到進程范圍或集群范圍的緩存內查詢,如果還是沒有查到,那么只有到數據庫中查詢。事務范圍的緩存是持久化層的第一級緩存,通常它是必需的;進程范圍或集群范圍的緩存是持久化層的第二級緩存,通常是可選的。
    1.2.    持久化層的緩存的并發訪問策略
    當多個并發的事務同時訪問持久化層的緩存的相同數據時,會引起并發問題,必須采用必要的事務隔離措施。
    在進程范圍或集群范圍的緩存,即第二級緩存,會出現并發問題。因此可以設定以下四種類型的并發訪問策略,每一種策略對應一種事務隔離級別。
    1) 事務型(Transactional)策略:僅僅在受管理環境中適用。它提供了Repeatable Read事務隔離級別。對于經常被讀但很少修改的數據,可以采用這種隔離類型,因為它可以防止臟讀和不可重復讀這類的并發問題。
    2) 讀寫型(read-write)策略:提供了Read Committed事務隔離級別。僅僅在非集群的環境中適用。對于經常被讀但很少修改的數據,可以采用這種隔離類型,因為它可以防止臟讀這類的并發問題。
    3) 非嚴格讀寫型(nonstrict-read-write)策略:不保證緩存與數據庫中數據的一致性。如果存在兩個事務同時訪問緩存中相同數據的可能,必須為該數據配置一個很短的數據過期時間,從而盡量避免臟讀。對于極少被修改,并且允許偶爾臟讀的數據,可以采用這種并發訪問策略。
    4) 只讀型策略(read-only):對于從來不會修改的數據,如參考數據,可以使用這種并發訪問策略。
    事務型并發訪問策略是事務隔離級別最高,只讀型的隔離級別最低。事務隔離級別越高,并發性能就越低。
    2.    Hibernate中的緩存:
    Hibernate中提供了兩級Cache,第一級別的緩存是Session級別的緩存,它是屬于事務范圍的緩存。這一級別的緩存由hibernate管理的,一般情況下無需進行干預;第二級別的緩存是SessionFactory級別的緩存,它是屬于進程范圍或群集范圍的緩存。這一級別的緩存可以進行配置和更改,并且可以動態加載和卸載。
    Hibernate還為查詢結果提供了一個查詢緩存,它依賴于第二級緩存。
    2.1.    一級緩存和二級緩存的比較:

    第一級緩存
    第二級緩存
    存放數據的形式
    相互關聯的持久化對象
    對象的散裝數據
    緩存的范圍
    事務范圍,每個事務都有單獨的第一級緩存
    進程范圍或集群范圍,緩存被同一個進程或集群范圍內的所有事務共享
    并發訪問策略
    由于每個事務都擁有單獨的第一級緩存,不會出現并發問題,無需提供并發訪問策略
    由于多個事務會同時訪問第二級緩存中相同數據,因此必須提供適當的并發訪問策略,來保證特定的事務隔離級別
    數據過期策略
    沒有提供數據過期策略。處于一級緩存中的對象永遠不會過期,除非應用程序顯式清空緩存或者清除特定的對象
    必須提供數據過期策略,如基于內存的緩存中的對象的最大數目,允許對象處于緩存中的最長時間,以及允許對象處于緩存中的最長空閑時間
    物理存儲介質
    內存
    內存和硬盤。對象的散裝數據首先存放在基于內在的緩存中,當內存中對象的數目達到數據過期策略中指定上限時,就會把其余的對象寫入基于硬盤的緩存中。
    緩存的軟件實現
    在Hibernate的Session的實現中包含了緩存的實現
    由第三方提供,Hibernate僅提供了緩存適配器(CacheProvider)。用于把特定的緩存插件集成到Hibernate中。
    啟用緩存的方式
    只要應用程序通過Session接口來執行保存、更新、刪除、加載和查詢數據庫數據的操作,Hibernate就會啟用第一級緩存,把數據庫中的數據以對象的形式拷貝到緩存中,對于批量更新和批量刪除操作,如果不希望啟用第一級緩存,可以繞過Hibernate API,直接通過JDBC API來執行指操作。
    用戶可以在單個類或類的單個集合的粒度上配置第二級緩存。如果類的實例被經常讀但很少被修改,就可以考慮使用第二級緩存。只有為某個類或集合配置了第二級緩存,Hibernate在運行時才會把它的實例加入到第二級緩存中。
    用戶管理緩存的方式
    第一級緩存的物理介質為內存,由于內存容量有限,必須通過恰當的檢索策略和檢索方式來限制加載對象的數目。Session的evit()方法可以顯式清空緩存中特定對象,但這種方法不值得推薦。
    第二級緩存的物理介質可以是內存和硬盤,因此第二級緩存可以存放大量的數據,數據過期策略的maxElementsInMemory屬性值可以控制內存中的對象數目。管理第二級緩存主要包括兩個方面:選擇需要使用第二級緩存的持久類,設置合適的并發訪問策略:選擇緩存適配器,設置合適的數據過期策略。
    2.2.    一級緩存的管理:
    當應用程序調用Session的save()、update()、savaeOrUpdate()、get()或load(),以及調用查詢接口的list()、iterate()或filter()方法時,如果在Session緩存中還不存在相應的對象,Hibernate就會把該對象加入到第一級緩存中。當清理緩存時,Hibernate會根據緩存中對象的狀態變化來同步更新數據庫。
    Session為應用程序提供了兩個管理緩存的方法:
    evict(Object obj):從緩存中清除參數指定的持久化對象。
    clear():清空緩存中所有持久化對象。
    2.3.    二級緩存的管理:
    2.3.1.      Hibernate的二級緩存策略的一般過程如下:
    1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數據庫,一次獲得所有的數據對象。 
    2) 把獲得的所有數據對象根據ID放入到第二級緩存中。 
    3) 當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢數據庫,把結果按照ID放入到緩存。 
    4) 刪除、更新、增加數據的時候,同時更新緩存。
      Hibernate的二級緩存策略,是針對于ID查詢的緩存策略,對于條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query Cache。
    2.3.2.      什么樣的數據適合存放到第二級緩存中?
    1 很少被修改的數據
    2 不是很重要的數據,允許出現偶爾并發的數據
    3 不會被并發訪問的數據
    4 參考數據,指的是供應用參考的常量數據,它的實例數目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。
    2.3.3.      不適合存放到第二級緩存的數據?
    1 經常被修改的數據
    2 財務數據,絕對不允許出現并發
    3 與其他應用共享的數據。
    2.3.4.      常用的緩存插件
    Hibernater 的二級緩存是一個插件,下面是幾種常用的緩存插件:
    l EhCache:可作為進程范圍的緩存,存放數據的物理介質可以是內存或硬盤,對Hibernate的查詢緩存提供了支持。
    l OSCache:可作為進程范圍的緩存,存放數據的物理介質可以是內存或硬盤,提供了豐富的緩存數據過期策略,對Hibernate的查詢緩存提供了支持。
    l SwarmCache:可作為群集范圍內的緩存,但不支持Hibernate的查詢緩存。
    l JBossCache:可作為群集范圍內的緩存,支持事務型并發訪問策略,對Hibernate的查詢緩存提供了支持。
    2.3.5.      配置二級緩存的主要步驟:
    1)      選擇需要使用二級緩存的持久化類,設置它的命名緩存的并發訪問策略。這是最值得認真考慮的步驟。
    2)      選擇合適的緩存插件,然后編輯該插件的配置文件。
     
     
    1.  首先設置EhCache,建立配置文件ehcache.xml,默認的位置在class-path,可以放到你的src目錄下:
    <ehcache>
        <diskStore path="c:\\ehcache\"/> 
        <defaultCache 
            maxElementsInMemory="10000" 
            eternal="false" 
            timeToIdleSeconds="120" 
            timeToLiveSeconds="120" 
            overflowToDisk="true"   
            />
            
        <!-- 設置Category類的緩存的數據過期策略 -->
        <cache name="org.qiujy.domain.cachedemo.Category"
            maxElementsInMemory="100"
            eternal="true"
            timeToIdleSeconds="0"
            timeToLiveSeconds="0"
            overflowToDisk="false"
            />
            
         <!-- 設置Category類的products集合的緩存的數據過期策略 -->
         <cache name="org.qiujy.domain.cachedemo.Category.products"
            maxElementsInMemory="500"
            eternal="false"
            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            overflowToDisk="true"
            />
            
        <cache name="org.qiujy.domain.cachedemo.Product"
            maxElementsInMemory="500"
            eternal="false"
            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            overflowToDisk="true"
            />    
    </ehcache>
    配置的元素說明:
    元素或屬性
    描述
    <diskStore>
    設置緩存數據文件的存放目錄
    <defaultCache>
    設置緩存的默認數據過期策略
    <cache>
    設定具體的命名緩存的數據過期策略
    每個命名緩存代表一個緩存區域,每個緩存區域有各自的數據過期策略。命名緩存機制使得用戶能夠在每個類以及類的每
      2.  在Hibernate配置文件中設置:

    <hibernate-configuration>
    <session-factory>……<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><property name="cache.use_second_level_cache">true</property>……</session-factory></hibernate-configuration>        此外,可以把cache.use_second_level_cache設置為false關閉所有的hibernate二級緩存。但此屬性對指定<cache>的類缺省為true。
     
       3.  為了使用二級緩存,需要在每一個Hibernate Entity上配置。
    @Entity   
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)    
    public class Forest { ... }   
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)    
    @JoinColumn(name="CUST_ID")    
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)    
    public SortedSet getTickets() {    
        return tickets;    
    }   
    @Cache(    
        CacheConcurrencyStrategy usage();                 (1)    
        String region() default "";                       (2)    
        String include() default "all";                   (3)    
    )   
    (1) usage: 提供緩存對象的事務隔離機制,可選值有以下幾種
    (NONE, READ_ONLY, NONSTRICT_READ_WRITE(非嚴格讀寫), READ_WRITE, TRANSACTIONAL)
    (2) region (optional): 指定緩存的區域,默認是類的全限定名。利用緩存區域,可以更精確的指定每個區域的緩存超前策略。如果指定了緩存區域前綴(在hibernate.cfg.xml中設置cache.region_prefix屬性為一個字符串),則所有的緩存區域名前將加上這個前綴。
    (3) include (optional): all to include all properties, non-lazy to only include non lazy properties (default all).
    如果不是使用annotation的話,則是在Hbm文件中添加cache usage="read-only"



    http://blog.163.com/seara520@126/blog/static/7206930420102232340810/
    posted @ 2012-05-14 09:24 abin 閱讀(1112) | 評論 (0)編輯 收藏

    1.EhCache是什么
        EhCache是Hibernate的二級緩存技術之一,可以把查詢出來的數據存儲在內存或者磁盤,節省下次同樣查詢語句再次查詢數據庫,大幅減輕數據庫壓力;

    2.EhCache的使用注意點
        當用Hibernate的方式修改表數據(save,update,delete等等),這時EhCache會自動把緩存中關于此表的所有緩存全部刪除掉(這樣能達到同步)。但對于數據經常修改的表來說,可能就失去緩存的意義了(不能減輕數據庫壓力);

    3.EhCache使用的場合
        3.1比較少更新表數據
            EhCache一般要使用在比較少執行write操作的表(包括update,insert,delete等)[Hibernate的二級緩存也都是這樣];
        3.2對并發要求不是很嚴格的情況
            兩臺機子中的緩存是不能實時同步的;

    4.在項目做的實現
        4.1在工程的src目錄下添加ehcache.xml文件,內容如下:
            <?xml version="1.0" encoding="UTF-8"?>
            <ehcache>    
                <diskStore path="java.io.tmpdir" />
              <defaultCache maxElementsInMemory="5"<!--緩存可以存儲的總記錄量-->
                eternal="false"<!--緩存是否永遠不銷毀-->
                overflowToDisk="true"<!--當緩存中的數據達到最大值時,是否把緩存數據寫入磁盤-->
                timeToIdleSeconds="15"<!--當緩存閑置時間超過該值,則緩存自動銷毀-->
                    timeToLiveSeconds="120"<!--緩存創建之后,到達該緩存自動銷毀-->
              />
            </ehcache>
        4.2在Hibernate.cfg.xml中的mapping標簽上面加以下內容:

            <property name="show_sql">true</property>
            <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
            <property name="hibernate.cache.use_query_cache">true</property>
        4.3在要緩存的bean的hbm.xml文件中的class標簽下加入以下內容:
           <cache usage="read-only" /><!--也可讀寫-->
        4.4創建DAO,內容如下:
            Session s = HibernateSessionFactory.getSession();
            Criteria c = s.createCriteria(Xyz.class);
            c.setCacheable(true);//這句必須要有
            System.out.println("第一次讀取");
            List l = c.list();
            System.out.println(l.size());
            HibernateSessionFactory.closeSession();

            s = HibernateSessionFactory.getSession();
            c = s.createCriteria(Xyz.class);
            c.setCacheable(true);//這句必須要有
            System.out.println("第二次讀取");
            l = c.list();
            System.out.println(l.size());
            HibernateSessionFactory.closeSession();
       4.5這時你會看到打印出來的信息為(表示第二次并沒有去讀庫):
            第一次讀取
            Hibernate: *******
            13
            第二次讀取
            13

    配置Spring+hibernate使用ehcache作為second-level cache

    大量數據流動是web應用性能問題常見的原因,而緩存被廣泛的用于優化數據庫應用。cache被設計為通過保存從數據庫里load的數據來減少應用和數據 庫之間的數據流動。數據庫訪問只有當檢索的數據不在cache里可用時才必要。hibernate可以用兩種不同的對象緩存:first-level cache 和 second-level cache。first-level cache和Session對象關聯,而second-level cache是和Session Factory對象關聯。

            缺省地,hibernate已經使用基于每個事務的first-level cache。 Hibernate用first-level cache主要是減少在一個事務內的sql查詢數量。例如,如果一個對象在同一個事務內被修改多次,hibernate將只生成一個包括所有修改的 UPDATE SQL語句。為了減少數據流動,second-level cache在Session Factory級的不同事務之間保持load的對象,這些對象對整個應用可用,不只是對當前用戶正在運行的查詢。這樣,每次查詢將返回已經load在緩存 里的對象,避免一個或更多潛在的數據庫事務。

    下載ehcache,hibernate3.2必須要ehcache1.2以上才能支持。可以修改log4j配置文件log4j.logger.net.sf.hibernate.cache=debug查看日志

    1.在類路徑上ehcache.xml:

    <ehcache>

         <!-- Sets the path to the directory where cache .data files are created.

              If the path is a Java System Property it is replaced by
              its value in the running VM.

              The following properties are translated:
              user.home - User's home directory
              user.dir - User's current working directory
              java.io.tmpdir - Default temp file path -->
         <diskStore path="java.io.tmpdir"/>


         <!--Default Cache configuration. These will applied to caches programmatically created through
             the CacheManager.

             The following attributes are required:

             maxElementsInMemory             - Sets the maximum number of objects that will be created in memory
             eternal                         - Sets whether elements are eternal. If eternal,   timeouts are ignored and the
                                              element is never expired.
             overflowToDisk                  - Sets whether elements can overflow to disk when the in-memory cache
                                              has reached the maxInMemory limit.

             The following attributes are optional:
             timeToIdleSeconds               - Sets the time to idle for an element before it expires.
                                              i.e. The maximum amount of time between accesses before an element expires
                                              Is only used if the element is not eternal.
                                              Optional attribute. A value of 0 means that an Element can idle for infinity.
                                              The default value is 0.
             timeToLiveSeconds               - Sets the time to live for an element before it expires.
                                              i.e. The maximum time between creation time and when an element expires.
                                              Is only used if the element is not eternal.
                                              Optional attribute. A value of 0 means that and Element can live for infinity.
                                              The default value is 0.
             diskPersistent                  - Whether the disk store persists between restarts of the Virtual Machine.
                                              The default value is false.
             diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
                                              is 120 seconds.
             -->

         <defaultCache
             maxElementsInMemory="10000"
             eternal="false"
             overflowToDisk="true"
             timeToIdleSeconds="120"
             timeToLiveSeconds="120"
             diskPersistent="false"
             diskExpiryThreadIntervalSeconds="120"/>
            
         <!-- See http://ehcache.sourceforge.net/documentation/#mozTocId258426 for how to configure caching for your objects -->
    </ehcache>

    2.applicationContext-hibernate.xml里Hibernate SessionFactory配置:

         <!-- Hibernate SessionFactory -->
         <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
             <property name="dataSource" ref="dataSource"/>
             <property name="configLocation"><value>classpath:hibernate.cfg.xml</value></property>
             <!-- The property below is commented out b/c it doesn't work when run via
                  Ant in Eclipse.   It works fine for individual JUnit tests and in IDEA ??
             <property name="mappingJarLocations">
                 <list><value>file:dist/appfuse-dao.jar</value></list>
             </property>
             -->
             <property name="hibernateProperties">
                 <props>
                     <prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop>
                     <!--<prop key="hibernate.show_sql">true</prop>-->
                     <prop key="hibernate.max_fetch_depth">3</prop>
                     <prop key="hibernate.hibernate.use_outer_join">true</prop>
                     <prop key="hibernate.jdbc.batch_size">10</prop>
                     <prop key="hibernate.cache.use_query_cache">true</prop>
                     <prop key="hibernate.cache.use_second_level_cache">true</prop>
                     <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                     <!--
                     <prop key="hibernate.use_sql_comments">false</prop>
                     -->
                     <!-- Create/update the database tables automatically when the JVM starts up
                     <prop key="hibernate.hbm2ddl.auto">update</prop> -->
                     <!-- Turn batching off for better error messages under PostgreSQL
                     <prop key="hibernate.jdbc.batch_size">0</prop> -->
                 </props>
             </property>
             <property name="entityInterceptor">
                <ref local="auditLogInterceptor"/>
             </property>
         </bean>
    說明:如果不設置“查詢緩存”,那么hibernate只會緩存使用load()方法獲得的單個持久化對象,如果想緩存使用findall()、 list()、Iterator()、createCriteria()、createQuery()等方法獲得的數據結果集的話,就需要設置 hibernate.cache.use_query_cache true 才行

    3.model類里采用Xdoclet生成*.hbm.xml里的cache xml標簽,即<cache usage="read-only"/>

    /**
    * @hibernate.class table="WF_WORKITEM_HIS"
    * @hibernate.cache usage="read-write"
    *
    */

    4.對于"query cache",需要在程序里編碼:

             getHibernateTemplate().setCacheQueries(true);
             return getHibernateTemplate().find(hql);

     

     

    使用spring和hibernate配置ehcache和query cache
     
    1、applicationContext.xml
    <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
    <prop key="hibernate.cache.use_query_cache">true</prop>

    這兩句加到hibernateProperties中
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
       <ref bean="sessionFactory" />
    </property>
    <property name="cacheQueries">
       <value>true</value>
    </property>
    </bean>

    添加此bean到applicationcontext.xml中。在各個DAO的bean中,更改如下
    <property name="sessionFactory">
    <ref bean="sessionFactory" />
    </property>
    改為
    <property name="hibernateTemplate">
    <ref bean="hibernateTemplate" />
    </property>

    2、ehcache.xml文件放在classes根目錄即可

    3、pojo與ehcache.xml的配置關系
    以com.ce.ceblog.pojos.CeblogJournal為例子
    在CeblogJournal.hbm.xml中配置:
    <class name="CeblogJournal" table="CEBLOG_JOURNAL" lazy="false">
    <cache usage="read-write" region="ehcache.xml中的name的屬性值"/>
    注意:這一句需要緊跟在class標簽下面,其他位置無效。

    Ehcache.xml文件主體如下
    <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1" timeToLiveSeconds="1" overflowToDisk="true" />
    <cache name="com.ce.ceblog.pojos.CeblogJournal" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" />
    hbm文件查找cache方法名的策 略:如果不指定hbm文件中的region="ehcache.xml中的name的屬性值",則使用name名為 com.ce.ceblog.pojos.CeblogJournal的cache,如果不存在與類名匹配的cache名稱,則用 defaultCache。
    如果CeblogJournal包含set集合,則需要另行指定其cache
    例如CeblogJournal包含ceblogReplySet集合,則需要
    添加如下配置到ehcache.xml中
    <cache name="com.ce.ceblog.pojos.CeblogJournal.ceblogReplySet"
    maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300"
    timeToLiveSeconds="600" overflowToDisk="true" />

    另,針對查詢緩存的配置如下:
    <cache name="org.hibernate.cache.UpdateTimestampsCache"
    maxElementsInMemory="5000"
    eternal="true"
    overflowToDisk="true"/>
    <cache name="org.hibernate.cache.StandardQueryCache"
    maxElementsInMemory="10000"
    eternal="false"
    timeToLiveSeconds="120"
    overflowToDisk="true"/>

    4、選擇緩存策略依據:
    <cache usage="transactional|read-write|nonstrict-read-write|read-only" />
    ehcache不支持transactional,其他三種可以支持。
    read- only:無需修改, 那么就可以對其進行只讀 緩存,注意,在此策略下,如果直接修改數據庫,即使能夠看到前臺顯示效果,但是將對象修改至cache中會報error,cache不會發生作用。另:刪 除記錄會報錯,因為不能在read-only模式的對象從cache中刪除。
    read-write:需要更新數據,那么使用讀/寫緩存 比較合適,前提:數據庫不可以為serializable transaction isolation level(序列化事務隔離級別)
    nonstrict-read-write:只偶爾需要更新數據(也就是說,兩個事務同時更新同一記錄的情況很不常見),也不需要十分嚴格的事務隔離,那么比較適合使用非嚴格讀/寫緩存策略。

    5、調試時候使用log4j的log4j.logger.org.hibernate.cache=debug,更方便看到ehcache的操作過程,主要用于調試過程,實際應用發布時候,請注釋掉,以免影響性能。

    6、 使用ehcache,打印sql語句是正常的,因為query cache設置為true將會創建兩個緩存區域:一個用于保存查詢結果集 (org.hibernate.cache.StandardQueryCache); 另一個則用于保存最近查詢的一系列表的時間戳(org.hibernate.cache.UpdateTimestampsCache)。請注意:在查詢 緩存中,它并不緩存結果集中所包含的實體的確切狀態;它只緩存這些實體的標識符屬性的值、以及各值類型的結果。需要將打印sql語句與最近的cache內 容相比較,將不同之處修改到cache中,所以查詢緩存通常會和二級緩存一起使用。

    posted @ 2012-05-13 02:08 abin 閱讀(319) | 評論 (0)編輯 收藏

    假設類A為持久化對象,對應表為tableA,這里沒有考慮A和其他表關聯的情況。

    在spring下配置使用二級緩存:

    <property name="hibernateProperties">
    <props>
    ........
    <prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
    <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
    </props>
    </property>

    其中${hibernate.cache.provider_class}為net.sf.ehcache.hibernate.EhCacheProvider,${hibernate.cache.use_query_cache}屬性值為true(對經常使用的List查詢方式,只有在使用查詢緩存時,才會從緩存中通過id去get緩存的值;查詢緩存一般緩存查詢語句和查詢結果的id)

    A的持久化映射文件中加上cache元素:usage屬性的取值根據自己的情況自己指定相應的值

    <cache usage="read-write"/>

    配置spring的HibernateTemplate對查詢語句和結果緩存(cacheQueries值為true):

    <bean id="hibernateTemplate"
            <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        <property name="cacheQueries" value="${hibernate.cache.use_query_cache}"></property>
    </bean>
    開發的spring dao(集成HibernateDaoSupport)應該配置實用這個hibernateTemplate:

    <bean id="myDao" of HibernateDaoSupport">
    <property name="hibernateTemplate" ref="hibernateTemplate" />
    <property name="jdbcTemplate" ref="jdbcTemplate" />
    </bean>

    在src下新建ehcache.xml文件,文件內容如下:

    <ehcache>
    <diskStore path="java.io.tmpdir"/>

    <!--
            eternal:元素是否永久的;
            MemoryStoreEvictionPolicy:default is LRU
        -->
    <defaultCache         maxElementsInMemory="10000"
                eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"
                overflowToDisk="true"            diskPersistent="false"           diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"/>

    <cache name="cn.hnisi.persistence.mmedia.Dmtjbxx"
                   maxElementsInMemory="500"               eternal="false"
                   timeToIdleSeconds="2400"      timeToLiveSeconds="3600"
                   overflowToDisk="false"/>

    <cache name="org.hibernate.cache.StandardQueryCache"
            maxElementsInMemory="50" eternal="false" timeToIdleSeconds="600"
            timeToLiveSeconds="1200" overflowToDisk="false"/>

    <cache name="org.hibernate.cache.UpdateTimestampsCache"
            maxElementsInMemory="500" eternal="true" overflowToDisk="false"/>

    </ehcache>
    然后你可以使用HQL查詢對象了,比如"from A where name=?";

    跟蹤查詢的sql日志就可以看出第一次是查詢數據庫,第二次是從緩存中get(見Hibernate ReadWriteCache類的get方法)

    問題:什么樣的數據適合存放到第二級緩存中?

    1 很少被修改的數據
    2 不是很重要的數據,允許出現偶爾并發的數據
    3 不會被并發訪問的數據
    4 參考數據,指的是供應用參考的常量數據,它的實例數目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。


    本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/selley/archive/2008/03/13/2177479.aspx

    posted @ 2012-05-13 02:07 abin 閱讀(1936) | 評論 (0)編輯 收藏

    package com.abin.lee.sort;

    public class QuickSort {
     public static void quick(int[] number) {
      sort(number, 0, number.length - 1);
     }

     private static void sort(int[] number, int left, int right) {
      if (left < right) {
       int i = left;
       int j = right + 1;
       while (true) {
        // 向右找
        while (i + 1 < number.length && number[++i] < number[left]);
        // 向左找
        while (j - 1 > -1 && number[--j] > number[left]);
        if (i >= j)
         break;
        swap(number, i, j);
       }
       swap(number, left, j);
       sort(number, left, j - 1);
       // 對左邊進行遞迴
       sort(number, j + 1, right);
       // 對右邊進行遞迴
      }
     }

     private static void swap(int[] number, int i, int j) {
      int t = number[i];
      number[i] = number[j];
      number[j] = t;
     }
     public static void main(String[] args) {
      int[] num=new int[]{1,8,4,2,7,5,6,3};
      quick(num);
      for(int i=0;i<num.length;i++){
       System.out.println(num[i]);
      }
     }
    }

    posted @ 2012-04-15 15:57 abin 閱讀(680) | 評論 (0)編輯 收藏

    在類中尋找指定的方法,同時獲取該方法的參數列表,例外和返回值

    package com.abin.lee.reflect;

    import java.lang.reflect.Method;

    public class method1 {
     private int f1(Object p,int x) throws NullPointerException{
      if(p==null)
       throw new NullPointerException();
      return x;
     }
     public static void main(String[] args) {
      try {
       Class cls=Class.forName("com.abin.lee.reflect.method1");
       Method[] method=cls.getDeclaredMethods();
       for(int i=0;i<method.length;i++){
        Method m=method[i];
        System.out.println("name="+m.getName());
        System.out.println("decl class="+m.getDeclaringClass());
        Class pvec[]=m.getParameterTypes();
        for(int j=0;j<pvec.length;j++)
         System.out.println("param#"+j+" "+pvec[j]);
        Class evec[]=m.getExceptionTypes();
        for(int k=0;k<evec.length;k++)
         System.out.println("evec="+evec[k]);
        System.out.println("return type="+m.getReturnType());
       }
       
       
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
     

    }






    獲取類的構造函數信息,基本上與獲取方法的方式相同

    package com.abin.lee.reflect;

    import java.lang.reflect.Constructor;

    public class constructor1 {
     public constructor1(){}
     public constructor1(int i,double d){}
     public static void main(String[] args) {
      try {
       Class<?> con=constructor1.class;
       Constructor cs[]=con.getConstructors();
       for(int i=0;i<cs.length;i++){
        Constructor ct=cs[i];
        System.out.println("name="+ct.getName());
        System.out.println("decl class="+ct.getDeclaringClass());
        Class pvec[]=ct.getParameterTypes();
        for(int j=0;j<pvec.length;j++){
         System.out.println("param="+pvec[j]);
        }
        Class excp[]=ct.getExceptionTypes();
        for(int j=0;j<excp.length;j++){
         System.out.println("exception="+excp[j]);
        }
        
        
       }
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
    }







    獲取類中的各個數據成員對象,包括名稱。類型和訪問修飾符號:

    package com.abin.lee.reflect;

    import java.lang.reflect.Field;

    public class FieldTest {
     private double d;
     public static final int i=37;
     String s="testing";
     public static void main(String[] args) {
      Class<?> cls=FieldTest.class;
      Field field[]=cls.getDeclaredFields();
      for(int i=0;i<field.length;i++){
       Field fd=field[i];
       System.out.println("name="+fd.getName());
       System.out.println("class="+fd.getDeclaringClass());
       System.out.println("type="+fd.getType());
       int mod=fd.getModifiers();
       System.out.println("modifiers="+java.lang.reflect.Modifier.toString(mod));
       
      }
      
      
      
     }
    }


    posted @ 2012-04-15 00:25 abin 閱讀(744) | 評論 (1)編輯 收藏

    僅列出標題
    共50頁: First 上一頁 39 40 41 42 43 44 45 46 47 下一頁 Last 
    主站蜘蛛池模板: 中文字幕无码亚洲欧洲日韩| 日韩人妻无码免费视频一区二区三区 | 亚洲色成人网站WWW永久| 国产成A人亚洲精V品无码| 亚洲黑人嫩小videos| 国产精品久久亚洲不卡动漫| 日韩国产欧美亚洲v片| 成人免费乱码大片A毛片| 91高清免费国产自产拍2021| 色婷婷7777免费视频在线观看| 国产zzjjzzjj视频全免费 | 亚洲香蕉成人AV网站在线观看| 亚洲高清在线视频| 亚洲综合精品第一页| 羞羞视频在线观看免费| 99爱在线观看免费完整版| 午夜免费福利影院| 亚洲小说区图片区另类春色| 亚洲youjizz| 一区二区三区视频免费| 亚洲网站免费观看| 亚洲AV无码专区日韩| 亚洲第一成年男人的天堂| 亚洲国产高清国产拍精品| 人妻在线日韩免费视频| 成人免费视频一区二区三区| 亚洲乱亚洲乱妇无码麻豆| 亚洲综合无码一区二区痴汉| 黄色视屏在线免费播放| 男人的好看免费观看在线视频| 国产成人综合亚洲AV第一页 | 亚洲乱码日产精品一二三| 在线观看片免费人成视频播放| 91视频国产免费| 亚洲国产婷婷六月丁香| 亚洲精品无播放器在线播放| 一个人免费日韩不卡视频| 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 免费成人在线观看| 亚洲国产成人精品电影| 国产精品偷伦视频免费观看了|