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

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

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

    深藍色心情

    過來聊聊~~~~

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      31 Posts :: 0 Stories :: 46 Comments :: 0 Trackbacks

    #

    如何不用寫java代碼來完成開發? 

    對于大部分的產品和項目來說,頁面變化是非常頭痛的事情。每次小功能上線,新客戶到來,都需要進行定制改造,不斷的開發維護。每次開發一方面要改動頁面,一方面要改動服務器代碼,然后部署。而借助動態數據源,可以不用開發后端應用,直接完成功能開發。 

    新功能開發時,只需要定義需要的數據格式和獲取方法,如通過xml上傳1個sql語句,系統根據sql語句自動提取數據并轉成通用的格式。開發過程中,后臺java開發部分只是寫好sql并且上傳,這樣前臺通過某一個servlet可以動態的讀取執行sql,并將結果按照json返給前端,以后所有的開發只需要前端做ajax實現頁面即可。 

    完整業務流程如下: 

    1. 用戶在前端操作,如需要讀取經濟類圖書。 

    2. 前端js判斷是什么操作,然后發送ajax請求到:http://services.guzz.org/commonServlet?id=f2354239sfASASFASfasf6&catId=47&keyword=jingji..... 

    3. 服務器端有一個類似dispatcher-servlet的東西(我們這兒的commonServlet),攔截請求,根據id知道加載數據需要執行名稱為f2354239sfASASFASfasf6的sql文件,執行時需要參數:catId=47和keyword=jingji 

    4. commonServlet從文件系統中讀取f2354239sfASASFASfasf6.xml文件(這個文件在一個隱藏的目錄下,從瀏覽器是不能直接獲取到的;集群環境會存放在集中存儲上),解析sql以及對象映射ORM。 

    5. commonServlet打開數據庫連接,根據sql構造查詢語句,將第一步傳入的參數全部作為命名參數傳給查詢語句,執行查詢。 

    6. commonServlet把查詢的ResultSet根據ORM轉成java類,再轉成json,返回前臺。 

    7. 前臺根據json構造出頁面并展示。結束流程。 

    在整個過程中,有2個關鍵步驟,一是動態加載SQL并進行ORM映射,一是自動進行sql所需要參數的類型轉換和匹配,進行命名查詢。如果系統規模較大,還需要解決查詢時分庫分表的問題。對于這種sql使用方式,由于在系統上線時,并不知道以后會用哪些sql語句,我們稱作動態SQL。 

    實現方式: 

    步驟1. 實現servlet。定義一個普通的servlet,或者jsp,或者webwork/spring action,接收參數,獲取到sql的id,以及所有傳入的參數,然后轉入處理類處理。處理完成后,將返回結果轉成json返回前端。 

    步驟2. 實現動態SQL加載與查詢。處理類根據id加載sql并執行,返回數據庫查詢結果。guzz 1.2.8 beta2提供了動態SQL服務,根據此服務可以直接實現此功能。詳細說明:http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

    好處: 

    實現以后,基本上后臺開發就會很穩定很穩定了,大部分的工作只是前端做頁面。可以大幅度的降低開發成本,提高開發進度。 

    上面的實現是以上傳文件來定義和管理sql,也可以通過數據庫來管理。這樣管理起來更加簡單。 

    如果使用guzz作為動態SQL提供者,可以自動獲得命名查詢,類型自動匹配(轉成枚舉類型都可以),分庫,自動分切表,自定義屬性表等附加支持。

    嘖嘖~~ 

    posted @ 2010-05-27 14:52 深藍色心情 閱讀(2969) | 評論 (5)編輯 收藏


    guzz是一套用來解決ORM、多數據源管理、以及通用數據計算的數據層框架,為系統在數據層的設計提供一站式解決方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代這2個東西。 

    guzz主要功能與特點: 
    • 現代大規模系統設計,技術上吸收了ibatis/hibernate的優點
    • 支持像hibernate一樣的對象化持久、映射和方便的增刪改查
    • 支持像ibatis一樣,讓dba參與sql設計的復雜數據庫操作和優化
    • 支持在線加載與調試SQL。按照應用策略,從文件/數據庫/Web Service等途徑,動態提取與使用SQL語句(Dynamic SQL)
    • 支持應用程序使用大量的數據庫和主從讀寫分離
    • 支持超越范式的特殊關聯、非結構化數據等異構資源的統一管理
    • 支持數據表在多組機器間水平分布(Shard),并自動維護多組機器之間的分布式事務
    • 支持1張表按照業務規則分切成多張小表(Shadow),并支持每張小表擁有自己特殊的屬性字段(Custom)
    • 支持組件化服務(SOA),構建企業/項目實施基礎平臺
    • 提供面向對象的數據庫讀取標簽(JSP Taglib),加快頁面展示層的快速變更、開發與部署
    • 支持配置管理服務器,可以使用一套軟件系統對所有應用程序的配置進行統一管理
    項目地址:http://code.google.com/p/guzz/ 
    文檔:http://code.google.com/p/guzz/wiki/WikiHomePage?tm=6 

    1.2.8 beta2更新介紹: 

    支持動態管理SQL: 

    動態SQL(Dynamic SQL)不是指應用程序動態的拼接SQL語句,動態SQL是指應用程序可以動態的獲取配置好的SQL語句。在獲取的過程中,SQL語句如何管理,由應用系統自身決定。 

    換句話說,在ibatis中,SQL語句配置到ibatis.xml文件中,在guzz中,配置到guzz.xml中。但當配置完成后,在系統運行期間這些SQL都是不能變動的,如果需要添加1個或者修改優化1個SQL語句,必須重啟應用才能生效。而動態SQL允許應用系統動態的管理(添加/修改/優化/刪除)sql語句以及查詢結果到對象的映射關系(ORM),對于SQL的變更不再需要重啟應用系統,以簡化維護與應對需求變化。 

    動態SQL主要有兩種應用場景:SQL優化和動態數據源。具體介紹請參看:http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

    改進遠程服務設計: 

    增加對hessian, burlap協議的支持。目前guzz內置支持phprpc, hessian, burlap三種協議進行RPC遠程調用。使用時,三種協議可以透明替換,類似spring對RMI類協議的封裝。具體介紹請參看:http://code.google.com/p/guzz/wiki/TutorialFutureService 

    增加枚舉類型與類型參數化支持: 

    按照TopLink的模式,支持JDK5 enum。Enum在使用時和普通類型一樣,不需要實現特殊的接口(hibernate要求實現接口)。Enum支持通過JPA的Enumeration注釋聲明,也支持在hbm.xml中通過xml定義。通過xml的定義方式參看:http://code.google.com/p/guzz/wiki/TutorialHbmXml 

    類型參數化為guzz的特殊功能,用于處理動態SQL參數和Jsp Taglib條件參數時,將String類型自動轉換成需要的數據類型。參數化類型主要為日期和枚舉。詳細介紹:http://code.google.com/p/guzz/wiki/TutorialHbmXml 

    增加對數據庫保留字的支持: 

    在定義數據庫列名時,可以用`(ESC下面的鍵)將列名引起來,避免字段名稱與數據庫保留字沖突。此功能與hibernate提供的處理保留字方法相同,但guzz只支持字段,不支持`表名`。 

    增加對Microsoft SQL Server的支持(未測試): 

    參考hibernate實現了一個SQL Server 2000 & 2005的dialect,不支持分頁。沒有測試過。Dialect實現類:org.guzz.dialect.MSSQLDialect 

    Guzz已經能夠支持的數據庫和數據類型請參看: 
    http://code.google.com/p/guzz/wiki/TutorialGuzzXml 

    應用示例說明: 

    http://code.google.com/p/guzz/wiki/TutorialDynamicSQLService 

    下一版本計劃: 

    • 修復發現的bug。
    • 設計一些常見的服務,推廣guzz基礎服務理念。
    posted @ 2010-05-26 10:13 深藍色心情 閱讀(1732) | 評論 (2)編輯 收藏

         摘要: guzz是一套用來解決ORM、多數據源管理、以及通用數據計算的數據層框架,為系統在數據層的設計提供一站式解決方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代這2個東西。  guzz主要功能與特點:  現代大規模系統設計,技術上吸收了ibatis/hibernate的優點 支持像hibernate一樣的對象化持久...  閱讀全文
    posted @ 2010-05-05 10:36 深藍色心情 閱讀(1431) | 評論 (0)編輯 收藏

    guzz是一套用來解決ORM、多數據源管理、以及通用數據計算的數據層框架,為系統在數據層的設計提供一站式解決方案。guzz可以看作是 ibatis/hibernate的一大的延伸,并可以取代這2個東西。 

    guzz主要功能與特點: 
    • 現代大規模系統設計,技術上吸收了ibatis/hibernate的優點
    • 支持像hibernate一樣的對象化持久、映射和方便的增刪改查
    • 支持像ibatis一樣,讓dba參與sql設計的復雜數據庫操作和優化
    • 支持應用程序使用大量的數據庫和主從讀寫分離
    • 支持超越范式的特殊關聯、非結構化數據等異構資源的統一管理
    • 支持數據表在多組機器間水平分布(Shard),并自動維護多組機器之間的分布式事務
    • 支持1張表按照業務規則分切成多張小表(Shadow),并支持每張小表擁有自己特殊的屬性字段(Custom)
    • 支持組件化服務(SOA),構建企業/項目實施基礎平臺
    • 提供面向對象的數據庫讀取標簽(JSP Taglib),加快頁面展示層的快速變更、開發與部署
    • 支持配置管理服務器,可以使用一套軟件系統對所有應用程序的配置進行統一管理
    項目地址:http://code.google.com/p/guzz/ 
    文檔:http://www.guzz.org/wiki/GuzzGuide 

    1.2.7正式版 更新介紹: 

    • 支持表分切。允許同一對象按照業務規則,分別存儲在不同的表中。如新聞評論:新聞頻道的評論存放在 tb_c1,娛樂:tb_c2,體育tb_c3,其他:tb_c4,滿足同類在線數據的數據表平行擴展需要。表分切命名為:Shadow Table。

    • 支持自定義屬性表。允許分切后的每張小表擁有自己的動態對象屬性和字段。如購物網站中:商品對象擁有統一的名稱、價格、編號、評分等,但不同的商品可能有自己特殊的屬性,如圖書擁有ISBN和出版社作者,服裝擁有尺碼、顏色、款式等等。自定義屬性允許程序只定義1個商品域對象,然后通過自定義屬性和切表,將每1種特定的商品分切到1張自己特殊的表中,這張表同時擁有商品通用的字段以及這種商品自己的字段,查詢時可以按照特殊字段直接在數據庫中進行關系查詢。在guzz中,自定義屬性的定義允許存儲到數據庫中,像普通對象一樣動態生成和管理,不用配置復雜的xml。自定義屬性命名為:Custom Table。

    • 增加并行任務支持。用于多個遠程服務同步的調用,降低等待時間。

    • 增加hilo和seqhilo主健生成策略。至此,hibernate支持的常見主健生成策略,guzz都支持了。

    • 增加外掛環境接口。如果在spring中啟動,允許在guzz中獲取spring定義的bean。
    應用示例說明: 

    本次更新有很多新概念需要介紹,因此篇幅較長。詳細的示例和說明請參看: 

    表分切:http://www.guzz.org/wiki/GuzzShadow 

    自定義屬性表(基于表分切):[url]http://www.guzz.org/wiki/GuzzCustomTable [/url] 

    并行任務執行(基于服務):http://www.guzz.org/wiki/GuzzFutureService 

    主健生成策略:http://www.guzz.org/wiki/GuzzHbm 

    下一版本計劃: 

    • 數據庫自動分庫支持。允許同一張表,分散在多臺數據庫中。
    • 提供更多對服務的支持。
    • 探索SASS(軟件就是服務)的數據層模型。
    • 其他
    posted @ 2010-04-09 14:55 深藍色心情 閱讀(1539) | 評論 (1)編輯 收藏

    我們主要是web應用,web規模也不能確定,有可能一天幾千萬甚至上億的PV,也有可能根本沒人用。最初設計guzz的目的就是讓大型網站和小型網站一樣設計編寫,因為誰也不知道這個應用上去以后有多少人用,同時解決系統被要求頁面天天改來該去的問題。 

    使用guzz以來的效果: 

    1. 框架性能上沒有看得出的快慢區別。我覺得不會比hibernate和biatis慢,我看過他們的一些代碼,流程挺復雜的。guzz很簡單,整個持久化過程需要轉手的類至少要比這兩個少很多。 

    2. 以前我們用hibernate較多,一般數據庫設計就是一個庫,讀寫全部做。現在在設計時大家腦子里面直接就是分出3個數據庫(可能部署在1臺mysql上)--業務主庫,臨時信息庫,日志庫,然后把表分到不同的庫中。然后數據庫安裝時直接主從安裝,主從使用。雖然看起來庫復雜了,但程序上沒有任何成本代價,基本上已經形成一種設計流程。這種模式感覺可以作為最佳實踐。 

    3. 編程上,一開始開發人員還是建個spring action類 + 在dao和manager中增加需要的方法 + 修改dispatcher-servlet.xml配置映射 + jsp實現view。但現在很多功能都是直接jsp,用taglib直接讀庫,基本上后臺的讀數據庫操作頁面已經看不到action的影子了。java代碼比先前的工程,同樣的功能少了大概60%-70%。 

    4. 我們的系統一般后臺功能比較復雜,以往編輯要改點東西大家都很郁悶。不過現在抵制少了很多,基本上就是改改jsp或者在復制1個新的jsp改改,然后傳到服務器上,一大堆集群機器的重啟工作都免了,無論是開發還是部署都很省事。和php差不多。 

    guzz1.2.7分表和自定義表的應用實例: 

    我們有1套調查系統,使用了這項技術,也是第一個線上測試。每個調查都不太一樣,需要網友填一些東西,需要填什么,填的個數類型都不定。一個調查進行過程中,或者結束后要求對數據進行統計報表。統計的內容可能也包括那些自定義的填空題。 

    在1.2.7之前,我們解決方案是:將所有自定義的調查項,按照key-value生成一個xml字符串,存儲到數據庫大字段中(Mysql text字段)。需要統計時,根據mysql5.1對xml支持的新特性使用ExtraValue函數解析這個xml生成一個新表(create table xxxx select ExtraValue(xx) as a, .....from 主調查記錄表),然后在根據新的xxxx表統計。每次都要手工來弄,非常繁瑣。 

    1.2.7,使用切表和自定義屬性后,現在的解決方案:每次創建投票并建立好自定義調查項(自定義調查項存儲在數據庫中),根據這些自動生成一個mysql create table的語句,創建好需要的表。在配置CustomTableView動態的映射用戶提交的數據存儲到對應的表中。完全自動,后續處理簡化了很多。 

    而且由于整個過程是實時的,以前的過程是手工的,所以很多線上的報表功能也可以開發了。開發也非常簡單,我們用guzz jsp tablib直接讀庫,像操作普通java屬性一樣操作自定義屬性,一個類型的表報1個jsp。特殊調查的特殊報表也就是往服務器上放1個特殊處理的jsp,應用都不用重啟,非常方便。 

    guzz1.2.7分表和自定義表的下一個應用計劃: 

    這是一個計劃,還沒有做,不過我們準備很快就開始做。 

    我們的所有系統對日志都有要求,日志必須記錄!但日志的開發很煩人,全是沒有技術含量的重復工作。我們準備開發一個日志服務,所有系統以后就不用開發日志了,直接使用這個服務。日志服務分為服務器端和客戶端。 

    服務器端: 

    一個標準的java web系統,有日志數據庫,用來存儲所有系統的日志信息,并提供查詢和統計等界面。如果有人需要查日志,就到這個系統來查。 

    服務器端有1個應用數據庫,用來創建和管理授權的應用系統。1個新的應用上線的時候,在這里創建一個應用和他的授權碼,然后錄入他的個性日志字段和數據類型(類似上面提到調查的個性選項),服務器自動在數據庫中給他創建1個日志表,用來存儲這個應用的日志數據。我們準備按季度分表,讓每個日志表1個季度分成1張子表。 

    客戶端: 

    實現一個標準的guzz service,提供日志插入接口 
    Java代碼 
    1. public void log(UserLog log) ;  

    每個系統開發時,將日志服務的jar包放到工程中,并在guzz.xml中聲明此服務,代碼直接調用就OK了。 

    這樣以后就不用為每個系統開發日志管理模塊了。并且還能獲取到統計某一個用戶在所有系統中活動記錄的額外增強(例如我們可以在服務器端將日志記錄兩份,一份按應用系統,一份按操做者記錄)~~ 

    posted @ 2010-04-09 14:52 深藍色心情 閱讀(3411) | 評論 (0)編輯 收藏

    提高 Linux 上 socket 性能

    加速網絡應用程序的 4 種方法

    developerWorks
     

    未顯示需要 JavaScript 的文檔選項


     


    級別: 中級

    M. Tim Jones ,資深軟件工程師,Emulex

    2006 年 2 月 13 日

    使用 Sockets API,我們可以開發客戶機和服務器應用程序,它們可以在本地網絡上進行通信,也可以通過 Internet 在全球范圍內進行通信。與其他 API 一樣,您可以通過一些方法使用 Sockets API,從而提高 Socket 的性能,或者限制 Socket 的性能。本文探索了 4 種使用 Sockets API 來榨取應用程序的最大性能并對 GNU/Linux? 環境進行優化從而達到最好結果的方法。

    在開發 socket 應用程序時,首要任務通常是確保可靠性并滿足一些特定的需求。利用本文中給出的 4 個提示,您就可以從頭開始為實現最佳性能來設計并開發 socket 程序。本文內容包括對于 Sockets API 的使用、兩個可以提高性能的 socket 選項以及 GNU/Linux 優化。

    為了能夠開發性能卓越的應用程序,請遵循以下技巧:

    • 最小化報文傳輸的延時。
    • 最小化系統調用的負載。
    • 為 Bandwidth Delay Product 調節 TCP 窗口。
    • 動態優化 GNU/Linux TCP/IP 棧。

    技巧 1. 最小化報文傳輸的延時

    在通過 TCP socket 進行通信時,數據都拆分成了數據塊,這樣它們就可以封裝到給定連接的 TCP payload(指 TCP 數據包中的有效負荷)中了。TCP payload 的大小取決于幾個因素(例如最大報文長度和路徑),但是這些因素在連接發起時都是已知的。為了達到最好的性能,我們的目標是使用盡可能多的可用數據來填充每個報文。當沒有足夠的數據來填充 payload 時(也稱為最大報文段長度(maximum segment size) 或 MSS),TCP 就會采用 Nagle 算法自動將一些小的緩沖區連接到一個報文段中。這樣可以通過最小化所發送的報文的數量來提高應用程序的效率,并減輕整體的網絡擁塞問題。

    盡管 John Nagle 的算法可以通過將這些數據連接成更大的報文來最小化所發送的報文的數量,但是有時您可能希望只發送一些較小的報文。一個簡單的例子是 telnet 程序,它讓用戶可以與遠程系統進行交互,這通常都是通過一個 shell 來進行的。如果用戶被要求用發送報文之前輸入的字符來填充某個報文段,那么這種方法就絕對不能滿足我們的需要。

    另外一個例子是 HTTP 協議。通常,客戶機瀏覽器會產生一個小請求(一條 HTTP 請求消息),然后 Web 服務器就會返回一個更大的響應(Web 頁面)。

    解決方案

    您應該考慮的第一件事情是 Nagle 算法滿足一種需求。由于這種算法對數據進行合并,試圖構成一個完整的 TCP 報文段,因此它會引入一些延時。但是這種算法可以最小化在線路上發送的報文的數量,因此可以最小化網絡擁塞的問題。

    但是在需要最小化傳輸延時的情況中,Sockets API 可以提供一種解決方案。要禁用 Nagle 算法,您可以設置 TCP_NODELAY socket 選項,如清單 1 所示。


    清單 1. 為 TCP socket 禁用 Nagle 算法
    
    int sock, flag, ret;
    
    /* Create new stream socket */
    sock = socket( AF_INET, SOCK_STREAM, 0 );
    
    /* Disable the Nagle (TCP No Delay) algorithm */
    flag = 1;
    ret = setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );
    
    if (ret == -1) {
      printf("Couldn't setsockopt(TCP_NODELAY)\n");
      exit(-1);
    }
    

    提示:使用 Samba 的實驗表明,在從 Microsoft? Windows? 服務器上的 Samba 驅動器上讀取數據時,禁用 Nagle 算法幾乎可以加倍提高讀性能。



    回頁首


    技巧 2. 最小化系統調用的負載

    任何時候通過一個 socket 來讀寫數據時,您都是在使用一個系統調用(system call)。這個調用(例如 readwrite)跨越了用戶空間應用程序與內核的邊界。另外,在進入內核之前,您的調用會通過 C 庫來進入內核中的一個通用函數(system_call())。從 system_call() 中,這個調用會進入文件系統層,內核會在這兒確定正在處理的是哪種類型的設備。最后,調用會進入 socket 層,數據就是在這里進行讀取或進行排隊從而通過 socket 進行傳輸的(這涉及數據的副本)。

    這個過程說明系統調用不僅僅是在應用程序和內核中進行操作的,而且還要經過應用程序和內核中的很多層次。這個過程耗費的資源很高,因此調用次數越多,通過這個調用鏈進行的工作所需要的時間就越長,應用程序的性能也就越低。

    由于我們無法避免這些系統調用,因此惟一的選擇是最小化使用這些調用的次數。幸運的是,我們可以對這個過程進行控制。

    解決方案

    在將數據寫入一個 socket 時,盡量一次寫入所有的數據,而不是執行多次寫數據的操作。對于讀操作來說,最好傳入可以支持的最大緩沖區,因為如果沒有足夠多的數據,內核也會試圖填充整個緩沖區(另外還需要保持 TCP 的通告窗口為打開狀態)。這樣,您就可以最小化調用的次數,并可以實現更好的整體性能。



    回頁首


    技巧 3. 為 Bandwidth Delay Product 調節 TCP 窗口

    TCP 的性能取決于幾個方面的因素。兩個最重要的因素是鏈接帶寬(link bandwidth)(報文在網絡上傳輸的速率)和 往返時間(round-trip time) 或 RTT(發送報文與接收到另一端的響應之間的延時)。這兩個值確定了稱為 Bandwidth Delay Product(BDP)的內容。

    給定鏈接帶寬和 RTT 之后,您就可以計算出 BDP 的值了,不過這代表什么意義呢?BDP 給出了一種簡單的方法來計算理論上最優的 TCP socket 緩沖區大小(其中保存了排隊等待傳輸和等待應用程序接收的數據)。如果緩沖區太小,那么 TCP 窗口就不能完全打開,這會對性能造成限制。如果緩沖區太大,那么寶貴的內存資源就會造成浪費。如果您設置的緩沖區大小正好合適,那么就可以完全利用可用的帶寬。下面我們來看一個例子:

    BDP = link_bandwidth * RTT

    如果應用程序是通過一個 100Mbps 的局域網進行通信,其 RRT 為 50 ms,那么 BDP 就是:

    100MBps * 0.050 sec / 8 = 0.625MB = 625KB

    注意:此處除以 8 是將位轉換成通信使用的字節。

    因此,我們可以將 TCP 窗口設置為 BDP 或 1.25MB。但是在 Linux 2.6 上默認的 TCP 窗口大小是 110KB,這會將連接的帶寬限制為 2.2MBps,計算方法如下:

    throughput = window_size / RTT

    110KB / 0.050 = 2.2MBps

    如果使用上面計算的窗口大小,我們得到的帶寬就是 12.5MBps,計算方法如下:

    625KB / 0.050 = 12.5MBps

    差別的確很大,并且可以為 socket 提供更大的吞吐量。因此現在您就知道如何為您的 socket 計算最優的緩沖區大小了。但是又該如何來改變呢?

    解決方案

    Sockets API 提供了幾個 socket 選項,其中兩個可以用于修改 socket 的發送和接收緩沖區的大小。清單 2 展示了如何使用 SO_SNDBUFSO_RCVBUF 選項來調整發送和接收緩沖區的大小。

    注意:盡管 socket 緩沖區的大小確定了通告 TCP 窗口的大小,但是 TCP 還在通告窗口內維護了一個擁塞窗口。因此,由于這個擁塞窗口的存在,給定的 socket 可能永遠都不會利用最大的通告窗口。


    清單 2. 手動設置發送和接收 socket 緩沖區大小
    
    int ret, sock, sock_buf_size;
    
    sock = socket( AF_INET, SOCK_STREAM, 0 );
    
    sock_buf_size = BDP;
    
    ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
                       (char *)&sock_buf_size, sizeof(sock_buf_size) );
    
    ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
                       (char *)&sock_buf_size, sizeof(sock_buf_size) );
    

    在 Linux 2.6 內核中,發送緩沖區的大小是由調用用戶來定義的,但是接收緩沖區會自動加倍。您可以進行 getsockopt 調用來驗證每個緩沖區的大小。

    巨幀(jumbo frame)

    我們還可以考慮將包的大小從 1,500 字節修改為 9,000 字節(稱為巨幀)。在本地網絡中可以通過設置最大傳輸單元(Maximum Transmit Unit,MTU)來設置巨幀,這可以極大地提高性能。

    就 window scaling 來說,TCP 最初可以支持最大為 64KB 的窗口(使用 16 位的值來定義窗口的大小)。采用 window scaling(RFC 1323)擴展之后,您就可以使用 32 位的值來表示窗口的大小了。GNU/Linux 中提供的 TCP/IP 棧可以支持這個選項(以及其他一些選項)。

    提示:Linux 內核還包括了自動對這些 socket 緩沖區進行優化的能力(請參閱下面 表 1 中的 tcp_rmemtcp_wmem),不過這些選項會對整個棧造成影響。如果您只需要為一個連接或一類連接調節窗口的大小,那么這種機制也許不能滿足您的需要了。



    回頁首


    技巧 4. 動態優化 GNU/Linux TCP/IP 棧

    標準的 GNU/Linux 發行版試圖對各種部署情況都進行優化。這意味著標準的發行版可能并沒有對您的環境進行特殊的優化。

    解決方案

    GNU/Linux 提供了很多可調節的內核參數,您可以使用這些參數為您自己的用途對操作系統進行動態配置。下面我們來了解一下影響 socket 性能的一些更重要的選項。

    /proc 虛擬文件系統中存在一些可調節的內核參數。這個文件系統中的每個文件都表示一個或多個參數,它們可以通過 cat 工具進行讀取,或使用 echo 命令進行修改。清單 3 展示了如何查詢或啟用一個可調節的參數(在這種情況中,可以在 TCP/IP 棧中啟用 IP 轉發)。


    清單 3. 調優:在 TCP/IP 棧中啟用 IP 轉發
    
    [root@camus]# cat /proc/sys/net/ipv4/ip_forward
    0
    [root@camus]# echo "1" > /poc/sys/net/ipv4/ip_forward
    [root@camus]# cat /proc/sys/net/ipv4/ip_forward
    1
    [root@camus]#
    

    表 1 給出了幾個可調節的參數,它們可以幫助您提高 Linux TCP/IP 棧的性能。

    表 1. TCP/IP 棧性能使用的可調節內核參數
    可調節的參數 默認值 選項說明
    /proc/sys/net/core/rmem_default "110592" 定義默認的接收窗口大小;對于更大的 BDP 來說,這個大小也應該更大。
    /proc/sys/net/core/rmem_max "110592" 定義接收窗口的最大大小;對于更大的 BDP 來說,這個大小也應該更大。
    /proc/sys/net/core/wmem_default "110592" 定義默認的發送窗口大小;對于更大的 BDP 來說,這個大小也應該更大。
    /proc/sys/net/core/wmem_max "110592" 定義發送窗口的最大大小;對于更大的 BDP 來說,這個大小也應該更大。
    /proc/sys/net/ipv4/tcp_window_scaling "1" 啟用 RFC 1323 定義的 window scaling;要支持超過 64KB 的窗口,必須啟用該值。
    /proc/sys/net/ipv4/tcp_sack "1" 啟用有選擇的應答(Selective Acknowledgment),這可以通過有選擇地應答亂序接收到的報文來提高性能(這樣可以讓發送者只發送丟失的報文段);(對于廣域網通信來說)這個選項應該啟用,但是這會增加對 CPU 的占用。
    /proc/sys/net/ipv4/tcp_fack "1" 啟用轉發應答(Forward Acknowledgment),這可以進行有選擇應答(SACK)從而減少擁塞情況的發生;這個選項也應該啟用。
    /proc/sys/net/ipv4/tcp_timestamps "1" 以一種比重發超時更精確的方法(請參閱 RFC 1323)來啟用對 RTT 的計算;為了實現更好的性能應該啟用這個選項。
    /proc/sys/net/ipv4/tcp_mem "24576 32768 49152" 確定 TCP 棧應該如何反映內存使用;每個值的單位都是內存頁(通常是 4KB)。第一個值是內存使用的下限。第二個值是內存壓力模式開始對緩沖區使用應用壓力的上限。第三個值是內存上限。在這個層次上可以將報文丟棄,從而減少對內存的使用。對于較大的 BDP 可以增大這些值(但是要記住,其單位是內存頁,而不是字節)。
    /proc/sys/net/ipv4/tcp_wmem "4096 16384 131072" 為自動調優定義每個 socket 使用的內存。第一個值是為 socket 的發送緩沖區分配的最少字節數。第二個值是默認值(該值會被 wmem_default 覆蓋),緩沖區在系統負載不重的情況下可以增長到這個值。第三個值是發送緩沖區空間的最大字節數(該值會被 wmem_max 覆蓋)。
    /proc/sys/net/ipv4/tcp_rmem "4096 87380 174760" tcp_wmem 類似,不過它表示的是為自動調優所使用的接收緩沖區的值。
    /proc/sys/net/ipv4/tcp_low_latency "0" 允許 TCP/IP 棧適應在高吞吐量情況下低延時的情況;這個選項應該禁用。
    /proc/sys/net/ipv4/tcp_westwood "0" 啟用發送者端的擁塞控制算法,它可以維護對吞吐量的評估,并試圖對帶寬的整體利用情況進行優化;對于 WAN 通信來說應該啟用這個選項。
    /proc/sys/net/ipv4/tcp_bic "1" 為快速長距離網絡啟用 Binary Increase Congestion;這樣可以更好地利用以 GB 速度進行操作的鏈接;對于 WAN 通信應該啟用這個選項。

    與任何調優努力一樣,最好的方法實際上就是不斷進行實驗。您的應用程序的行為、處理器的速度以及可用內存的多少都會影響到這些參數影響性能的方式。在某些情況中,您認為有益的操作可能恰恰是有害的(反之亦然)。因此,我們需要逐一試驗各個選項,然后檢查每個選項的結果。換而言之,我們需要相信自己的經驗,但是對每次修改都要進行驗證。

    提示:下面介紹一個有關永久性配置的問題。注意,如果您重新啟動了 GNU/Linux 系統,那么您所需要的任何可調節的內核參數都會恢復成默認值。為了將您所設置的值作為這些參數的默認值,可以使用 /etc/sysctl.conf 在系統啟動時將這些參數配置成您所設置的值。



    回頁首


    GNU/Linux 工具

    GNU/Linux 對我非常有吸引力,這是因為其中有很多工具可以使用。盡管其中大部分都是命令行工具,但是它們都非常有用,而且非常直觀。GNU/Linux 提供了幾個工具 —— 有些是 GNU/Linux 自己提供的,有些是開放源碼軟件 —— 用于調試網絡應用程序,測量帶寬/吞吐量,以及檢查鏈接的使用情況。

    表 2 列出最有用的幾個 GNU/Linux 工具,以及它們的用途。表 3 列出了 GNU/Linux 發行版沒有提供的幾個有用工具。有關表 3 中工具的更多信息請參閱 參考資料

    表 2. 任何 GNU/Linux 發行版中都可以找到的工具
    GNU/Linux 工具 用途
    ping 這是用于檢查主機的可用性的最常用的工具,但是也可以用于識別帶寬延時產品計算的 RTT。
    traceroute 打印某個連接到網絡主機所經過的包括一系列路由器和網關的路徑(路由),從而確定每個 hop 之間的延時。
    netstat 確定有關網絡子系統、協議和連接的各種統計信息。
    tcpdump 顯示一個或多個連接的協議級的報文跟蹤信息;其中還包括時間信息,您可以使用這些信息來研究不同協議服務的報文時間。

    表 3. GNU/Linux 發行版中沒有提供的有用性能工具
    GNU/Linux 工具 用途
    netlog 為應用程序提供一些有關網絡性能方面的信息。
    nettimer 為瓶頸鏈接帶寬生成一個度量標準;可以用于協議的自動優化。
    Ethereal 以一個易于使用的圖形化界面提供了 tcpump(報文跟蹤)的特性。
    iperf 測量 TCP 和 UDP 的網絡性能;測量最大帶寬,并匯報延時和數據報的丟失情況。



    回頁首


    結束語

    嘗試使用本文中介紹的技巧和技術來提高 socket 應用程序的性能,包括通過禁用 Nagle 算法來減少傳輸延時,通過設置緩沖區的大小來提高 socket 帶寬的利用,通過最小化系統調用的個數來降低系統調用的負載,以及使用可調節的內核參數來優化 Linux 的 TCP/IP 棧。

    在進行優化時還需要考慮應用程序的特性。例如,您的應用程序是基于 LAN 的還是會通過 Internet 進行通信?如果您的應用程序僅僅會在 LAN 內部進行操作,那么增大 socket 緩沖區的大小可能不會帶來太大的改進,不過啟用巨幀卻一定會極大地改進性能!

    最后,還要使用 tcpdumpEthereal 來檢查優化之后的結果。在報文級看到的變化可以幫助展示使用這些技術進行優化之后所取得的成功效果。



    回頁首


    參考資料

    學習

    獲得產品和技術

    討論
    posted @ 2006-02-15 09:34 深藍色心情 閱讀(430) | 評論 (0)編輯 收藏

    Oracle Database 10g (10.1.0.2) Installation On RedHat Advanced Server 4.0

    In this article I'll describe the installation of Oracle Database 10g (10.1.0.2) on RedHat Advanced Server 4.0. The article is based on a server installation with a minimum of 2G swap, secure Linux disabled and the following package groups installed:
    • X Window System
    • GNOME Desktop Environment
    • Editors
    • Graphical Internet
    • Text-based Internet
    • Server Configuration Tools
    • Development Tools
    • Administration Tools
    • System Tools
    Alternative installations may require additional packages to be loaded in addition to the ones listed below.

    Download Software

    Download the following software:

    Unpack Files

    First unzip the files:
    gunzip ship.db.cpio.gz
    Next unpack the contents of the files:
    cpio -idmv < ship.db.cpio
    You should now have a single directory (Disk1) containing installation files.

    Hosts File

    The /etc/hosts file must contain a fully qualified name for the server:
    <IP-address>  <fully-qualified-machine-name>  <machine-name>

    Set Kernel Parameters

    Add the following lines to the /etc/sysctl.conf file:
    kernel.shmall = 2097152
    kernel.shmmax = 2147483648
    kernel.shmmni = 4096
    # semaphores: semmsl, semmns, semopm, semmni
    kernel.sem = 250 32000 100 128
    fs.file-max = 65536
    net.ipv4.ip_local_port_range = 1024 65000
    Run the following command to change the current kernel parameters:
    /sbin/sysctl -p
    Add the following lines to the /etc/security/limits.conf file:
    *               soft    nproc   2047
    *               hard    nproc   16384
    *               soft    nofile  1024
    *               hard    nofile  65536
    Add the following line to the /etc/pam.d/login file, if it does not already exist:
    session    required     /lib/security/pam_limits.so
    Note by Kent Anderson: In the event that pam_limits.so cannot set privilidged limit settings see Bug 115442.

    Disable secure linux by editing the /etc/selinux/config file, making sure the SELINUX flag is set as follows:
    SELINUX=disabled
    Alternatively, this alteration can be done using the GUI tool (Applications > System Settings > Security Level). Click on the SELinux tab and disable the feature.

    Setup

    Install the following packages:
    # From RedHat AS4 Disk 2
    cd /media/cdrom/RedHat/RPMS
    rpm -Uvh setarch-1.6-1.i386.rpm
    rpm -Uvh compat-libstdc++-33-3.2.3-47.3.i386.rpm
    
    # From RedHat AS4 Disk 3
    cd /media/cdrom/RedHat/RPMS
    rpm -Uvh openmotif-2.2.3-6.RHEL4.2.i386.rpm
    rpm -Uvh compat-db-4.1.25-9.i386.rpm
    
    # From RedHat AS4 Disk 4
    cd /media/cdrom/RedHat/RPMS
    rpm -Uvh compat-gcc-32-3.2.3-47.3.i386.rpm
    rpm -Uvh compat-gcc-32-c++-3.2.3-47.3.i386.rpm
    Create the new groups and users:
    groupadd oinstall
    groupadd dba
    groupadd oper
    
    useradd -g oinstall -G dba oracle
    passwd oracle
    Create the directories in which the Oracle software will be installed:
    mkdir -p /u01/app/oracle/product/10.1.0/db_1
    chown -R oracle.oinstall /u01
    Login as root and issue the following command:
    xhost +<machine-name>
    Edit the /etc/redhat-release file replacing the current release information (Red Hat Enterprise Linux AS release 4 (Nahant)) with the following:
    redhat-3
    Login as the oracle user and add the following lines at the end of the .bash_profile file:
    # Oracle Settings
    TMP=/tmp; export TMP
    TMPDIR=$TMP; export TMPDIR
    
    ORACLE_BASE=/u01/app/oracle; export ORACLE_BASE
    ORACLE_HOME=$ORACLE_BASE/product/10.1.0/db_1; export ORACLE_HOME
    ORACLE_SID=TSH1; export ORACLE_SID
    ORACLE_TERM=xterm; export ORACLE_TERM
    PATH=/usr/sbin:$PATH; export PATH
    PATH=$ORACLE_HOME/bin:$PATH; export PATH
    
    LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib; export LD_LIBRARY_PATH
    CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib; export CLASSPATH
    #LD_ASSUME_KERNEL=2.4.1; export LD_ASSUME_KERNEL
    
    if [ $USER = "oracle" ]; then
      if [ $SHELL = "/bin/ksh" ]; then
        ulimit -p 16384
        ulimit -n 65536
      else
        ulimit -u 16384 -n 65536
      fi
    fi

    Installation

    Log into the oracle user. If you are using X emulation then set the DISPLAY environmental variable:
    DISPLAY=<machine-name>:0.0; export DISPLAY
    Start the Oracle Universal Installer (OUI) by issuing the following command in the Disk1 directory:
    ./runInstaller
    During the installation enter the appropriate ORACLE_HOME and name then continue with a "software only" installation.

    Post Installation

    Create a new instance using the DBCA. If you get the "ORA-27125: unable to create shared memory segment" error when using the DBCA issue the following commands as the oracle user then try again:
    cd $ORACLE_HOME/bin
    
    mv oracle oracle.bin
    
    cat >oracle <<"EOF"
    #!/bin/bash
     
    export DISABLE_HUGETLBFS=1
    exec $ORACLE_HOME/bin/oracle.bin $@
    EOF
     
    chmod +x oracle
    I didn't encounter the previous issue myself, so hopefully you won't either.

    Edit the /etc/redhat-release file restoring the original release information:
    Red Hat Enterprise Linux AS release 4 (Nahant)
    Finally edit the /etc/oratab file setting the restart flag for each instance to 'Y':
    TSH1:/u01/app/oracle/product/10.1.0/db_1:Y
    Create a file called /etc/init.d/dbora containing the following:
    #!/bin/sh
    # description: Oracle auto start-stop script.
    # chkconfig: - 20 80
    #
    # Set ORA_HOME to be equivalent to the $ORACLE_HOME
    # from which you wish to execute dbstart and dbshut;
    #
    # Set ORA_OWNER to the user id of the owner of the 
    # Oracle database in ORA_HOME.
    ORA_HOME=/u01/app/oracle/product/10.1.0/db_1
    ORA_OWNER=oracle
    if [ ! -f $ORA_HOME/bin/dbstart ]
    then
        echo "Oracle startup: cannot start"
        exit
    fi
    case "$1" in
        'start')
            # Start the Oracle databases:
            # The following command assumes that the oracle login 
            # will not prompt the user for any values
            su - $ORA_OWNER -c "$ORA_HOME/bin/lsnrctl start"
            su - $ORA_OWNER -c $ORA_HOME/bin/dbstart
            ;;
        'stop')
            # Stop the Oracle databases:
            # The following command assumes that the oracle login 
            # will not prompt the user for any values
            su - $ORA_OWNER -c $ORA_HOME/bin/dbshut
            su - $ORA_OWNER -c "$ORA_HOME/bin/lsnrctl stop"
            ;;
    esac
    Use chmod to set the privileges to 750:
    chmod 750 /etc/init.d/dbora
    Link the file into the appropriate run-level script directories:
    ln -s /etc/init.d/dbora /etc/rc0.d/K10dbora
    ln -s /etc/init.d/dbora /etc/rc3.d/S99dbora
    Associate the dbora service with the appropriate run levels:
    chkconfig --level 345 dbora on
    The relevant instances should now startup/shutdown automatically at system startup/shutdown.

    For more information see:
    Hope this helps. Regards Tim...

    Back to the Top.
    posted @ 2006-01-19 14:08 深藍色心情 閱讀(843) | 評論 (0)編輯 收藏

         摘要: Here is a summary (HOWTO) how I installed: Oracle 9iR2 (9.2.0.6.0) Database on Red Hat Advanced Server 4 (x86, kernel 2.6.9-5.EL, glibc-2.3.4-2) Oracle 9iR2 (9.2.0) Database on Red Hat Advanced Server...  閱讀全文
    posted @ 2006-01-19 13:51 深藍色心情 閱讀(2340) | 評論 (0)編輯 收藏



    Hibernate配置文件可以有兩種格式,一種是 hibernate.properties ,另一種是 hibernate.cfg.xml 

    后者稍微方便一些,當增加hbm映射文件的時候,可以直接在 hibernate.cfg.xml 里面增加,不必像 hibernate.properties 必須在初始化代碼中加入。

    但不管怎么說,兩種的配置項都是一樣的,下面詳細介紹:

    在Hibernate的src目錄下有一個 hibernate.properties 模板,我們不必自己從頭寫,修改模板就可以了:)

    hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N' 


    這個配置意思是當你在Hibernate里面輸入true的時候,Hibernate會轉化為1插入數據庫,當你在Hibernate里面輸入false的時候,Hibernate會轉化為0插入數據庫,后面的Y,N同理。

    對于某些數據庫,例如Oracle來說,沒有boolean數據類型,就是采用1代表true,0代表false,因此使用這個配置在Hibernate里面直接用true/false會非常直觀。

    1hibernate.dialect net.sf.hibernate.dialect.MySQLDialect 
    2hibernate.connection.driver_class com.mysql.jdbc.Driver 
    3hibernate.connection.url jdbc:mysql:///test 
    4hibernate.connection.username root 
    5hibernate.connection.password  
    6


    這是一個連接MySQL數據庫的例子,很直觀,不必解釋,不同的數據庫的連接參數模板中全部給出了。


    hibernate.connection.pool_size 1
    hibernate.statement_cache.size 25

    這是Hibernate自帶的連接池的配置參數,在默認情況下將采用。意義很直觀,不多解釋。

    只是提醒一點,Hibernate這個連接池是非常原始非常簡單的連接池,如果你在項目中用Hibernate的話,建議你首選App Server的連接池,次選Hibernate帶的DBCP連接池。自帶的連接池應該做為末選。

    如果你采用DBCP連接池,除了要配置DBCP連接池以外,還需要取消掉下行的注釋:

    hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider

    其它的連接池同理。

    如果采用App Server的連接池,假設App Server連接池的DataSource的JNDI名稱為"mypool"的話,配置應該如下:

    hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
    hibernate.connection.datasource mypool
    hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider

    其它參數就不必寫了,因為已經在App Server配置連接池的時候指定好了。

    如果你不是在App Server環境中使用Hibernate,例如遠程客戶端程序,但是你又想用App Server的數據庫連接池,那么你還需要配置JNDI的參數,例如Hibernate連接遠程Weblogic上的數據庫連接池:

    hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
    hibernate.connection.datasource mypool
    hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider
    hibernate.jndi.class weblogic.jndi.WLInitialContextFactory
    hibernate.jndi.url t3://servername:7001/


    最后,如果你需要在EJB或者JTA中使用Hibernate,需要取消下行的注釋:

    hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory

    雜項配置:


    hibernate.show_sql false

    是否將Hibernate發送給數據庫的sql顯示出來,這是一個非常非常有用處的功能。當你在調試Hibernate的時候,讓Hibernate打印sql語句,可以幫助你迅速解決問題。


    #hibernate.connection.isolation 4

    指定數據庫的隔離級別,往往不同的數據庫有自己定義的隔離級別,未必是Hibernate的設置所能更改的,所以也不必去管它了。

    hibernate.jdbc.fetch_size 50 
    hibernate.jdbc.batch_size 25 


    這兩個選項非常非常非常重要!!!將嚴重影響Hibernate的CRUD性能!

    C = create, R = read, U = update, D = delete

    Fetch Size 是設定JDBC的Statement讀取數據的時候每次從數據庫中取出的記錄條數。

    例如一次查詢1萬條記錄,對于Oracle的JDBC驅動來說,是不會1次性把1萬條取出來的,而只會取出Fetch Size條數,當紀錄集遍歷完了這些記錄以后,再去數據庫取Fetch Size條數據。

    因此大大節省了無謂的內存消耗。當然Fetch Size設的越大,讀數據庫的次數越少,速度越快;Fetch Size越小,讀數據庫的次數越多,速度越慢。

    這有點像平時我們寫程序寫硬盤文件一樣,設立一個Buffer,每次寫入Buffer,等Buffer滿了以后,一次寫入硬盤,道理相同。

    Oracle數據庫的JDBC驅動默認的Fetch Size=10,是一個非常保守的設定,根據我的測試,當Fetch Size=50的時候,性能會提升1倍之多,當Fetch Size=100,性能還能繼續提升20%,Fetch Size繼續增大,性能提升的就不顯著了。

    因此我建議使用Oracle的一定要將Fetch Size設到50。

    不過并不是所有的數據庫都支持Fetch Size特性,例如MySQL就不支持。

    MySQL就像我上面說的那種最壞的情況,他總是一下就把1萬條記錄完全取出來,內存消耗會非常非常驚人!這個情況就沒有什么好辦法了 :(

    Batch Size是設定對數據庫進行批量刪除,批量更新和批量插入的時候的批次大小,有點相當于設置Buffer緩沖區大小的意思。

    Batch Size越大,批量操作的向數據庫發送sql的次數越少,速度就越快。我做的一個測試結果是當Batch Size=0的時候,使用Hibernate對Oracle數據庫刪除1萬條記錄需要25秒,Batch Size = 50的時候,刪除僅僅需要5秒!!!

    可見有多么大的性能提升!很多人做Hibernate和JDBC的插入性能測試會奇怪的發現Hibernate速度至少是JDBC的兩倍,就是因為Hibernate使用了Batch Insert,而他們寫的JDBC沒有使用Batch的緣故。

    以我的經驗來看,Oracle數據庫 Batch Size = 30 的時候比較合適,50也不錯,性能會繼續提升,50以上,性能提升的非常微弱,反而消耗內存更加多,就沒有必要了。


    #hibernate.jdbc.use_scrollable_resultset true

    設定是否可以使用JDBC2.0規范的可滾動結果集,這對Hibernate的分頁顯示有一定的作用,默認就好了。

    #hibernate.cglib.use_reflection_optimizer false 


    默認打開,啟用cglib反射優化。cglib是用來在Hibernate中動態生成PO字節碼的,打開優化可以加快字節碼構造的速度。

    不過,當你在調試程序過程中,特別是和proxy,lazy loading相關的應用中,代碼出錯,但是出錯提示信息有語焉不詳,那么你可以把cglib優化關掉,這樣Hibernate會輸出比較詳細的調試信息,幫助你debug。
    posted @ 2005-12-02 11:48 深藍色心情 閱讀(497) | 評論 (0)編輯 收藏

     
    數據庫驅動更新為classes12-9i.jar
    修改hibernate的配置如下
    代碼
    <bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"/>

    <bean id="oracleLobHandle" class="org.springframework.jdbc.support.lob.OracleLobHandler" Lazy-init="true">
     
    <property name="nativeJdbcExtractor">
       
    <ref local="nativejdbcExtractor"/>
     
    </property>
    </bean>


    在有clob類型sessionFactory(org.springframework.com.hibernate.LocalSessionFractoryBean)中加入
    <property name="lobHandler"><ref bean="oracleLobHandle"/></property>

    在需要clob的JavaBean對應的hbm.xml中,改對應的clob類型的字段

    代碼
    <property
     
    name=""
     type
    ="org.springframework.orm.hibernate.support.ClobStringType"
     clumn
    =""
     length
    ="XXXXXX" <!--定義clob字段大小(以字節為單位,最大2GB)-->
    >

    JavaBean的對應的屬性類型為String

    ------------------------------------------------------------------------------
    ----hibernate3 使用blob 和 clob 演例代碼-----

    hibernate3 使用blob 和 clob 演例代碼:

     1import java.io.File;
     2import java.io.FileInputStream;
     3import java.io.OutputStream;
     4import java.io.Writer;
     5import java.sql.Clob;
     6import oracle.sql.CLOB;
     7import org.hibernate.LockMode;
     8import org.hibernate.Transaction;
     9import org.hibernate.Session;
    10import org.hibernate.Hibernate;
    11import org.hibernate.lob.SerializableBlob;
    12import org.hibernate.lob.SerializableClob;
    13
    14
    15public class test1 {
    16
    17        /**
    18         * @param args
    19         */

    20        static Session session = HibernateSessionFactory.currentSession();
    21        
    22        public boolean inserted(TStu obj){
    23                
    24                Transaction tran = session.beginTransaction();
    25                session.save(obj);
    26                session.flush();
    27                session.refresh(obj,LockMode.UPGRADE);
    28                try
    29                {
    30                SerializableBlob sb = (SerializableBlob)obj.getImg();
    31                java.sql.Blob wrapblob = sb.getWrappedBlob();
    32                if(wrapblob instanceof oracle.sql.BLOB){
    33                         oracle.sql.BLOB blob = (oracle.sql.BLOB) wrapblob;
    34                OutputStream bout = blob.getBinaryOutputStream();
    35                FileInputStream fin = new FileInputStream("d:\\a.jpg");//修改你要存入的圖片
    36                byte [] buf = new byte[10240];//做為10K的緩存寫入
    37                int len;
    38                while((len = fin.read(buf))>0){
    39                        bout.write(buf,0,len);
    40                }

    41                bout.close();
    42                fin.close();
    43                }

    44                
    45                SerializableClob  sc = (SerializableClob)obj.getResu();
    46                Clob wrapclob = sc.getWrappedClob();
    47                if(wrapclob instanceof CLOB){
    48                        CLOB clob = (CLOB)wrapclob; 
    49                        Writer cout = clob.getCharacterOutputStream();
    50                        File file = new File("C:\\log_2005_8.txt");//修改你要存如的文本
    51                        FileInputStream fin = new FileInputStream(file);
    52                        int read;
    53                        while((read = fin.read())!= -1){
    54                                cout.write(read);
    55                        }

    56                        fin.close();
    57                        cout.close();
    58                }

    59                
    60                tran.commit();
    61                return true;
    62                }
    catch(Exception ex){
    63                        ex.printStackTrace();
    64                        tran.rollback();
    65                        return false;
    66                }

    67        }

    68        
    69        public static void main(String[] args) {
    70                // TODO Auto-generated method stub         
    71                test1 t = new test1();
    72                 TStu stu = new TStu();
    73                 stu.setAge(new Integer("23"));
    74                 stu.setName("lilei");
    75                 stu.setImg(Hibernate.createBlob(new byte[1]));
    76                 stu.setResu(Hibernate.createClob(" "));
    77                 t.inserted(stu);        
    78        }

    79}

    80
    81



    org link: http://www.matrix.org.cn/thread.shtml?topicId=27138&forumId=23
    posted @ 2005-11-18 10:42 深藍色心情 閱讀(2550) | 評論 (2)編輯 收藏

    僅列出標題
    共4頁: 上一頁 1 2 3 4 下一頁 
    主站蜘蛛池模板: 亚洲精品中文字幕无乱码| 久久国产免费一区| 亚洲精品123区在线观看| 亚洲一区二区三区在线网站| 亚洲一区二区观看播放| 一级毛片无遮挡免费全部| 成在人线av无码免费高潮水| 30岁的女人韩剧免费观看| 国产成人免费手机在线观看视频| 亚洲日本va在线视频观看| 亚洲精品成人网站在线播放| 亚洲人成在线免费观看| 色噜噜AV亚洲色一区二区| 亚洲中文久久精品无码1| 一区二区3区免费视频| 亚洲成A人片在线观看无码3D| 亚洲熟妇av一区二区三区下载| 色欲A∨无码蜜臀AV免费播 | 99精品视频免费| 99热在线精品免费全部my| 中文字幕第一页亚洲| 久久综合久久综合亚洲| 免费观看的毛片手机视频| 亚洲国产综合专区电影在线| 亚洲AV成人无码网天堂| 久久国产精品免费专区| 91亚洲国产在人线播放午夜| 久久WWW免费人成—看片| 日韩亚洲国产二区| 久久亚洲精品国产精品婷婷| 国产一区二区三区免费在线观看 | 国产亚洲精品自在久久| 亚洲av色香蕉一区二区三区蜜桃| 一本久久综合亚洲鲁鲁五月天 | 亚洲国产理论片在线播放| 一级毛片在线免费看| 久久亚洲精品专区蓝色区| 国产福利电影一区二区三区,亚洲国模精品一区 | 亚洲乱理伦片在线观看中字| ww在线观视频免费观看| 色窝窝亚洲av网|