posts - 40,  comments - 7,  trackbacks - 0
            2006年8月22日
          關于inode;


          inode 譯成中文就是索引節點。每個存儲設備或存儲設備的分區(存儲設備是硬盤、軟盤、U盤 ... ... )被格式化為文件系統后,應該有兩部份,一部份是inode,另一部份是Block,Block是用來存儲數據用的。而inode呢,就是用來存儲這些數據的信息,這些信息包括文件大小、屬主、歸屬的用戶組、讀寫權限等。inode為每個文件進行信息索引,所以就有了inode的數值。操作系統根據指令,能通過inode值最快的找到相對應的文件。

          做個比喻,比如一本書,存儲設備或分區就相當于這本書,Block相當于書中的每一頁,inode 就相當于這本書前面的目錄,一本書有很多的內容,如果想查找某部份的內容,我們可以先查目錄,通過目錄能最快的找到我們想要看的內容。雖然不太恰當,但還是比較形象。

          當我們用ls 查看某個目錄或文件時,如果加上-i 參數,就可以看到inode節點了;比如我們前面所說的例子;



          [root@localhost ~]# ls -li lsfile.sh
          2408949 -rwxr-xr-x 1 root root 7 04-21 12:47 lsfile.sh

          lsfile.sh 的inode值是 2408949 ; 查看一個文件或目錄的inode,要通過ls 命令的的 -i參數。


          2.10 inode 相同的文件是硬鏈接文件;


          在Linux 文件系統中,inode值相同的文件是硬鏈接文件,也就是說,不同的文件名,inode可能是相同的,一個inode值可以對應多個文件。理解鏈接文件并不難,看看例子就會了。在Linux中,鏈接文件是通過ln工具來創建的。


          2.11 創建硬鏈接,硬鏈接和源文件關系;


          用ln 創建文件硬鏈接的語法:



          # ln 源文件 目標文件

          下面我們舉一個例子,在這個例子中,我們要為sun.txt 創建其硬鏈接sun002.txt。然后看一下sun.txt和sun002.txt的屬性的變化;


          [root@localhost ~]# ls -li sun.txt 注:查看sun.txt的屬性;
          2408263 -rw-r--r-- 1 root root 29 04-22 21:02 sun.txt 注:這是sun.txt的屬性;
          [root@localhost ~]# ln sun.txt sun002.txt 注:我們通過ln 來創建sun.txt的硬鏈接文件sun002.txt
          [root@localhost ~]# ls -li sun* 注:我們列一下sun.txt 和sun002.txt
          2408263 -rw-r--r-- 2 root root 29 04-22 21:02 sun002.txt
          2408263 -rw-r--r-- 2 root root 29 04-22 21:02 sun.txt

          我們可以看到sun.txt在沒有創建硬鏈接文件sun002.txt的時候,其鏈接個數是1(也就是-rw-r--r--后的那個數值),創建了硬鏈接sun002.txt創建后,這個值變成了2。也就是說,我們每次為sun.txt創建一個新的硬鏈接文件后,其硬鏈接個數都會增加1。

          inode值相同的文件,他們的關系是互為硬鏈接的關系。當我們修改其中一個文件的內容時,互為硬鏈接的文件的內容也會跟著變化。如果我們刪除互為硬鏈接關系的某個文件時,其它的文件并不受影響。比如我們把sun.txt刪除后,我們還是一樣能看到sun002.txt的內容,并且sun02.txt仍是存在的。

          可以這么理解,互為硬鏈接關系的文件,他們好象是克隆體,他們的屬性幾乎是完全一樣;

          下面的例子,我們把sun.txt刪除,然后我們看一下sun002.txt 是不是能看到其內容。



          [root@localhost ~]# rm -rf sun.txt
          [root@localhost ~]# more sun002.txt

          注意:硬鏈接不能為目錄創建,只有文件才能創建硬鏈接。


          2.12 軟鏈接的創建,及軟接與源文件的關系;


          創建軟鏈接(也被稱為符號鏈接)的語法;



          # ln -s 源文文件或目錄 目標文件或目錄

          軟鏈接也叫符號鏈接,他和硬鏈接有所不同,軟鏈接文件只是其源文件的一個標記。當我們刪除了源文件后,鏈接文件不能獨立存在,雖然仍保留文件名,但我們卻不能查看軟鏈接文件的內容了。



          [root@localhost ~]# ls -li linuxsir001.txt
          2408274 -rw-r--r-- 1 root root 29 04-22 21:53 linuxsir001.txt
          [root@localhost ~]# ln -s linuxsir001.txt linuxsir002.txt
          [root@localhost ~]# ls -li linuxsir001.txt linuxsir002.txt
          2408274 -rw-r--r-- 1 root root 29 04-22 21:53 linuxsir001.txt
          2408795 lrwxrwxrwx 1 root root 15 04-22 21:54 linuxsir002.txt -> linuxsir001.txt

          解釋

          上面的例子,首先我們查看 linuxsir001.txt 的屬性,比如inode 、所屬文件種類、創建或修改時間等... ...我們來對比一下:

          首先 對比一下節點:兩個文件的節點不同;
          其次 兩個文件的歸屬的種類不同 linuxsir001.txt是-,也就是普通文件,而linuxsir002.txt 是l,它是一個鏈接文件;
          第三 兩個文件的讀寫權限不同 linuxsir001.txt 是rw-r--r-- ,而linuxsir002.txt的讀寫權限是 rwxrwxrwx
          第三 兩者的硬鏈接個數相同;都是1
          第四 兩文件的屬主和所歸屬的用戶組相同;
          第五 修改(或訪問、創建)時間不同;

          我們還注意到了linuxsir002.txt 后面有一個標記 ->,這表示linuxsir002.txt 是linuxsir001.txt的軟鏈接文件。

          值得我們注意的是:當我們修改鏈接文件的內容時,就意味著我們在修改源文件的內容。當然源文件的屬性也會發生改變,鏈接文件的屬性并不會發生變化。當我們把源文件刪除后,鏈接文件只存在一個文件名,因為失去了源文件,所以軟鏈接文件也就不存在了。這一點和硬鏈接是不同的;



          [root@localhost ~]# rm -rf linuxsir001.txt 注:刪除linuxsir001.txt
          [root@localhost ~]# ls -li linuxsir002.txt 注:查看linuxsir002 的屬性;
          2408795 lrwxrwxrwx 1 root root 15 04-22 21:54 linuxsir002.txt -> linuxsir001.txt
          [root@localhost ~]# more linuxsir002.txt 注:查看linuxsir002.txt的內容;
          linuxsir002.txt: 沒有那個文件或目錄 注:得到提示,linuxsir002.txt不存在。

          上面的例子告訴我們,如果一個鏈接文件失去了源,就意味著他已經不存在了;

          我們可以看到軟鏈接文件,其實只是源文件的一個標記,當源文件失去時,他也就是存在了。軟鏈接文件只是占用了inode來存儲軟鏈接文件屬性等信息,但文件存儲是指向源文件的。

          軟件鏈接,可以為文件或目錄都適用。無論是軟鏈接還是硬鏈接,都可以用rm來刪除。rm工具是通用的。
          參考資料:http://techcenter.dicder.com/2006/0908/content_185.htm
          posted @ 2007-07-13 09:54 Lansing 閱讀(750) | 評論 (0)編輯 收藏
          寫一些關于PL/SQL的語法,免得等到用到的時候還要去亂翻。
          1??刂屏鞒?if,while)
          2。循環(for)
          3。游標(cursor)
          4。異常處理(exception)

          1??刂屏鞒蹋ǎ?br />

          A.條件語句
          IF <statement> THEN
          ?? PL/SQL
          END IF;

          IF <statement> THEN
          ?? PL/SQL
          ELSE
          ?? PL/SQL
          END IF;

          IF
          <statement> THEN
          ?? PL/SQL
          ELSIF <statement> THEN
          ?? PL/SQL
          END IF;


          2。循環

          A.simple loop
          LOOP
          ?? SQL
          ?? EXIT WHEN <statement>;
          END LOOP;

          LOOP
          ?? SQL
          ?? IF
          <statement> THEN
          ?? EXIT;
          ?? END IF;
          END LOOP;

          B.While loop
          WHILE <statement> LOOP
          ?? SQL
          END LOOP;

          C.For loop
          FOR $counter in $low .. $high LOOP
          ?? SQL
          END LOOP


          3。游標

          在PL/SQL程序中定義的游標叫做顯式游標。

          A.顯式游標的處理由四個部分組成:
          cursor $cursorname is $Query;   --定義游標
          open $cursorname;         --打開游標
          fetch $cursorname into $othervariable  --把游標中的東西取出
          close $cursorname??? --關閉游標

          B.游標屬性
          %found?? ?? ?? 布爾型屬性,當最近一次讀紀錄成功
          ,為true.
          %nofound                失敗時,為false.
          %isopen
          %rowcount?? ?? 返回已從游標中讀取的記錄數。

          C.參數化游標

          所有的SQL語句在上下文區內部都是可執行的,因此都有一個游標指向上下文區,此游標就是所謂的SQL游標。
          與顯式游標不同,SQL游標不被程序打開和關閉。


          4.異常處理概念

          異常處理是用來處理正常執行過程中未預料的事件。如果PL/SQL程序塊一旦產生異常而又沒有指出如何處理時,程序會自動終止。
          異常處理部分放在PL/SQL的后半部分,結構為:

          EXCEPTION
          ?????? WHEN first_exception THEN <code to handle first exception>
          ?????? WHEN second_exception THEN <code to handle second exception>
          ?????? WHEN OTHERS THEN <
          code to handle second exception >? --OTHERS必須放在最后

          異常分為預定義和用戶定義兩種。
          用戶定義的異常是通過顯式使用RAISE語句來引發。如

          DECLARE
          ? e_TooManyStudents EXCEPTION;? -- 類型為Exception,用于指示錯誤條件
          ? v_CurrentStudents NUMBER(3);? -- HIS-101學生注冊當前號
          ? v_MaxStudents NUMBER(3);????? -- HIS-101學生注冊允許的最大號

          BEGIN
           /* 找出注冊學生當前號和允許的最大號 */

          ? SELECT current_students, max_students

          ??? INTO v_CurrentStudents, v_MaxStudents

          ??? FROM classes

          ??? WHERE department = 'HIS' AND course = 101;

          ? /* 檢查學生的號 */

          ? IF v_CurrentStudents > v_MaxStudents THEN

          /* 太多的學生注冊,則觸發例外處理 */

          ? RAISE e_TooManyStudents;

          ? END IF;

          EXCEPTION

          ? WHEN e_TooManyStudents THEN

          ??? /* 當太多的學生注冊,就插入信息解釋發生過錯誤 */

          ??? INSERT INTO log_table (info) VALUES ('History 101 has ' || v_CurrentStudents ||

          ????? 'students: max allowed is ' || v_MaxStudents);

          END;


          END;

          用戶定義的的異常處理
          可以使用RAISE_APPLICATION_ERROR來創建自己的錯誤處理:
          RAISE_APPLICATION_ERROR(error_number,error_message,[keep_errors]);
          其中
          error_number是從-20000到-20999之間的參數; error_message是相應的提示信息,小于512字節。如:

          CREATE OR REPLACE PROCEDURE Register (
          p_StudentID IN students.id%TYPE,
          p_Department IN classes.department%TYPE,
          p_Course IN classes.course%TYPE) AS
          v_CurrentStudents NUMBER;? -- 班上學生的當前號
          v_MaxStudents NUMBER;????? -- 班上學生的最大號

          BEGIN
          /* 找出學生的當前號和最大號 */
          SELECT current_students, max_students
          ?INTO v_CurrentStudents, v_MaxStudents
          FROM classes
          WHERE course = p_Course
          AND department = p_Department;

          /* 確認另外的學生是否有足夠的教室 */
          IF v_CurrentStudents + 1 > v_MaxStudents THEN
          RAISE_APPLICATION_ERROR(-20000, 'Can''t add more students to ' ||
          p_Department || ' ' || p_Course);
          END IF;

          /* 加一個學生在本班 */
          ClassPackage.AddStudent(p_StudentID, p_Department, p_Course);

          EXCEPTION
          WHEN NO_DATA_FOUND THEN
             
          RAISE_APPLICATION_ERROR(-20001, p_Department || ' ' || p_Course ||
          ??? ?? ??
          ' doesn''t exist!');
          END Register;

          posted @ 2007-01-23 10:10 Lansing 閱讀(373) | 評論 (0)編輯 收藏
          關于ODBC數據源連接文本?

          ????????????  在《外部數據庫的連接原理》一講中我們說過,ODBC提供對多種數據庫的支持,如dBase、Access、MS?SQL?
          ????????????Server及Oracle,也就是說運用ODBC數據源中所提供的連接代碼,我們可以實現對多種數據庫的連接。以連接Access數據庫為例,ODBC數據源連接文本的格式是:
          ????????????  “Driver={數據庫驅動程序};Dbq=數據庫文件;”
          ????????????  在以上連接文本中,如果數據庫跟程序在同一目錄下,或者用變量DefaultDir指定了數據庫所在目錄,則數據庫文件可以不用全路徑名,如下即可:
          ????????????  “ODBC;DBQ=MSAccess.mdb;Driver={Microsoft?Access?Driver?(*.mdb)};”
          ????????????  如下也可:
          ????????????  “ODBC;DBQ=MSAccess.mdb;DefaultDir=d:\Downloads\e21;Driver={Microsoft?
          ????????????Access?Driver?(*.mdb)};”
          ????????????  如果數據庫跟程序不在同一目錄下,或者沒有用變量DefaultDir指定數據庫所在目錄,則數據庫文件需要用全路徑名,如下:
          ????????????  “ODBC;DBQ=E:\Quake?III?Arena\MSAccess.mdb;Driver={Microsoft?Access?
          ????????????Driver?(*.mdb)};”
          ????????????  以上所說的是連接Access數據庫的格式,那么連接其他數據庫的ODBC數據源連接文本又是怎樣的?連接不同類型的數據庫要使用不同的對應驅動程序,沒忘記吧!不同的驅動程序當然它們的參數組合也就不同了,每一種不同驅動程序都有其特定的的參數形式:?

          ????????????  ⑴、MS?Access?ODBC?DSNless?連接:
          ????????????  ☆、參數:Driver?設置值:{Microsoft?Access?Driver?(*.mdb)}
          ????????????  ☆、參數:Dbq?設置值:實際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?Access?Driver?
          ????????????(*.mdb)};Dbq=c:\somepath\dbname.mdb;Uid=Admin;Pwd=pass;?”
          ???????????? ?、啤Base?ODBC?DSNless?連接:?
          ????????????  ☆、參數:Driver?設置值:{Microsoft?dBASE?Driver?(*.dbf)}
          ????????????  ☆、參數:Dbq?設置值:實際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?dBASE?Driver?
          ????????????(*.dbf)};DriverID=277;Dbq=c:\somepath\dbname.dbf;?”
          ????????????  ⑶、Oracle?ODBC?DSNless?連接:
          ????????????  ☆、參數:Driver?設置值:{Microsoft?ODBC?for?Oracle}
          ????????????  ☆、參數:Dbq?設置值:實際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?ODBC?for?
          ????????????Oracle};Server=OracleServer.world;Uid=admin;Pwd=pass;?”
          ????????????  ⑷、MS?SQL?Server?DSNless?連接:?
          ????????????  ☆、參數:Driver?設置值:{SQL?Server};
          ????????????  ☆、參數:Server?設置值:服務器名稱
          ????????????  ☆、參數:Database?設置值:數據表名稱
          ????????????  ☆、參數:Uid?設置值:用戶名稱
          ????????????  ☆、參數:Pwd?設置值:密碼
          ????????????  ☆、例句:
          ????????????  “Driver={SQL?
          ????????????Server};Server=servername;Database=dbname;Uid=sa;Pwd=pass;?”
          ????????????  ⑸、MS?Text?Driver?DSNless?連接:?
          ????????????  ☆、參數:Driver?設置值:{Microsoft?Text?Driver?(*.txt;?*.csv)}
          ????????????  ☆、參數:Dbq?設置值:實際路徑文件名稱
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?Text?Driver?(*.txt;?
          ????????????*.csv)};Dbq=c:\somepath\;Extensions=asc,csv,tab,txt;Persist?Security?
          ????????????Info=False;?”
          ???????????? ?、?、Visual?Foxpro?DSNless?連接:
          ????????????  ☆、參數:Driver?設置值:{Microsoft?Visual?FoxPro?Driver}
          ????????????  ☆、參數:SourceType?設置值:DBC
          ????????????  ☆、參數:SourceDB?設置值:實際路徑文件名稱?
          ????????????  ☆、例句:
          ????????????  “Driver={Microsoft?Visual?FoxPro?
          ????????????Driver};SourceType=DBC;SourceDB=c:\somepath\dbname.dbc;Exclusive=No;”?

          ????????????  ⑺、MySQL?DSNless?連接:
          ????????????  ☆、參數:Driver?設置值:{mysql}
          ????????????  ☆、參數:database?設置值:數據表名稱
          ????????????  ☆、參數:uid?設置值:用戶名稱
          ????????????  ☆、參數:pwd?設置值:密碼
          ????????????  ☆、例句:?
          ????????????  “driver={mysql};?
          ????????????database=yourdatabase;uid=username;pwd=password;option=16386”
          ????????????*******************************************************************
          ????????????SQL語言簡介?

          ????????????  在上一講中我們介紹了連接外部數據庫的方法,那么連接之后怎樣對外部數據庫進行讀取、顯示、增刪、更新、查詢等操作呢?這些操作需要通過外部數據庫等對象調用SQL指令才能完成。
          ???????????? ?、濉⑹裁词荢QL語言
          ????????????  SQL(Structure?Query?Languge,結構化查詢語言)是一種數據庫專用的計算機語言,不管是Oracle、MS?
          ????????????SQL?
          ????????????、Access、MySQL或其他公司的數據庫,也不管數據庫建立在大型主機或個人計算機上,都可以使用SQL語言來訪問和修改數據庫的內容。雖然不同公司的數據庫軟件多多少少會增加一些專屬的SQL語法,但大體上,它們還是遵循ASNI(美國國家標準協會)制定的SQL標準。因為SQL語言具有易學習及閱讀等特性,所以SQL逐漸被各種數據庫廠商采用,而成為一種共通的標準查詢語言。只要你學會SQL,即可操作各種數據庫如Visual?
          ????????????Foxpro、Access、dBase等等。總之,SQL語言是各種數據庫都可以使用的數據庫查詢語言。
          ????????????  SQL語言不僅僅具有查詢數據庫的功能,而且可以對數據庫完成選取、增刪、更新與跳轉等各種操作。
          ????????????  ㈡、SQL語言的組成
          ????????????  SQL語言是由命令(函數)、子句、運算符、加總函數及通配符等組成,分述如下:
          ????????????  1、命令
          ????????????  SQL的命令可分成數據定義語言與數據操作語言,數據定義語言可用來建立新的數據庫、數據表、字段及索引等,本教程不予介紹;另一為數據操作語言,可用來建立查詢表、排序、篩選數據、修改、增刪等動作。數據定義語言命令常用的有選擇、添加、刪除和修改這四種:
          ????????????  ⑴、命令:SELECT
          ????????????  中文意思:選擇
          ????????????  說明:用于找出合乎條件的記錄
          ???????????? ?、啤⒚睿篒NSERT
          ????????????  中文意思:插入
          ????????????  說明:用于增加一筆記錄或合并兩個數據表
          ????????????  ⑶、命令:UPDATE
          ????????????  中文意思:更新
          ????????????  說明:用于更正合乎條件的記錄
          ????????????  ⑷、命令:DELETE
          ????????????  中文意思:刪除
          ????????????  說明:用于刪除合乎條件的記錄
          ????????????  2、子句
          ????????????  子句是用于設定命令要操作的對象(即參數),SQL所用的子句如下:
          ????????????  ⑴、子句:FROM?
          ????????????  中文意思:數據表
          ????????????  說明:用于指定數據表
          ???????????? ?、啤⒆泳洌篧HERE
          ????????????  中文意思:條件
          ????????????  說明:用于設定條件
          ????????????  ⑶、GROUP?BY
          ????????????  中文意思:分組(合并)
          ????????????  說明:用于設定分組
          ???????????? ?、?、ORDER?BY
          ????????????  中文意思:排序
          ????????????  說明:用于設定輸出的順序及字段
          ????????????  3、運算符
          ????????????  子句參數中的運算符使子句構成不同的語法格式,如“字段1='100'”、“字段1>'100'”等。運算符又分邏輯運算符與比較運算符。
          ????????????  ◇邏輯運算符如下:
          ???????????? ?、拧⑦\算符:AND
          ????????????  中文意思:并且
          ????????????  說明:邏輯且
          ???????????? ?、?、運算符:OR?
          ????????????  中文意思:或者
          ????????????  說明:邏輯非
          ???????????? ?、恰⑦\算符:NOT
          ????????????  中文意思:取反
          ????????????  說明:邏輯非或邏輯反
          ????????????  ◇比較運算符如下:
          ????????????  ⑴、運算符:<?說明:小于
          ???????????? ?、啤⑦\算符:≤?說明:小于等于
          ???????????? ?、?、運算符:≥?說明:大于等于
          ????????????  ⑷、運算符:>?說明:大于
          ????????????  ⑸、運算符:=?說明:等于
          ???????????? ?、?、運算符:<>?說明:不等于
          ???????????? ?、?、運算符:BETWEEN?說明:用于設定范圍?中文意思:在...之間
          ????????????  ⑻、運算符:LIKE?說明:用于通配設定?中文意思:如同
          ???????????? ?、?、運算符:IN?說明:用于集合設定?中文意思:在...之內
          ????????????  4、加總函數
          ????????????  加總函數常常運用在命令的參數中,如:“SELECT?SUM(數學),AVG(數學)?FROM?成績單”。
          ???????????? ?、?、加總函數:AVG?
          ????????????  中文意思:平均
          ????????????  說明:用于求指定條件的平均?
          ???????????? ?、啤⒓涌偤瘮担篊OUNT
          ????????????  中文意思:數量
          ????????????  說明:用于求指定的數量
          ???????????? ?、恰⒓涌偤瘮担篠UM
          ????????????  中文意思:和
          ????????????  說明:用于求指定條件的和
          ???????????? ?、?、加總函數:MAX
          ????????????  中文意思:最大值
          ????????????  說明:用于求指定條件的最大值
          ????????????  ⑸、加總函數:MIN
          ????????????  中文意思:最小值
          ????????????  說明:用于求指定條件的最小值
          ????????????  5、通配符
          ????????????  ⑴、通配符:%?意義:任何長度的字符串(包括0)
          ????????????  ⑵、通配符:_?意義:下劃線表示任何一個字符
          ???????????? ?、?、通配符:[]?意義:中括號表示某個范圍內的一個字符
          ????????????  在下一講將說明SQL語言是怎樣把命令(函數)、子句、運算符、及加總函數等組合在一起的。

          ????????????*************************************************************************

          ????????????嵌入式SQL的應用?

          ????????????  SQL語句可以單獨在數據庫系統本身中執行,但如果運用在其他編程工具所編制的程序中,一般不能單獨執行,而要把SQL語句嵌入到高級語言(如易語言)中使用,通過高級語言的命令和方法來調用之,此時SQL稱為嵌入式SQL。調用SQL語句的程序稱為宿主程序,在易語言中一般是把SQL語句作為宿主程序的唯一參數來直接處理。嵌入式SQL在使用上有一些規定,在易語言中目前的版本規定如下:
          ???????????? ?、拧⒃诔绦蛑幸獏^分SQL語句和宿主語言的語句。在易語言中好區分,因為SQL語句形式是英文的,而易語言是中文的,但在實際應用時仍然有可能會混亂,所以易語言要把SQL語句轉化為文本型才能調用,即嵌入式SQL語句兩邊要用雙引號來標示。
          ????????????  ⑵、允許SQL語句使用宿主程序的變量,但使用時要將宿主程序的變量跟外部數據庫中表格的字段名區別開來,區別方法如下:
          ????????????  ①、在易語言中要將變量類型轉化為文本型變量才能被SQL文本相加使用,比如下面的例子中有一個叫“數字1”的整數類型變量,插入到SQL文本中是這樣表達:
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?”?+?組合框1.內容?+?“=”?+?到文本?(數字1))
          ???????????? ?、凇侄蚊腟QL文本兩邊加雙引號,變量名不能在雙引號內,如上例。
          ???????????? ?、?、要將字段名跟字段值區別開來,區別方法如下:
          ????????????  ①、對于文本類型的字段,在其字段值兩邊要加上“'”號標示其文本值,代表語法是:字段名稱=‘文本值’。如下:
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?姓名='山大王'”)
          ????????????  又如下面“查找編輯框.內容”中的字段值是文本型,嵌入式SQL語句如下:
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?姓名==”?+?“'”?+?查找編輯框.內容?+?
          “'”)
          ????????????  ②、對于數字類型的字段,在SQL語句中表示其字段值,兩邊不加符號標示,代表語法是:字段名稱=數字值。如下兩例:
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?”?+?組合框1.內容?+?“=”?+?查找編輯框.內容)?
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?學號=17”)
          ???????????? ?、?、對于日期時間類型的字段,在其字段值兩邊要加上“#”號標示其時間值,代表語法是:字段名稱=#時間值#。如下兩例:
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?入學時間?BETWEEN?#2001-01-01#?and?
          ????????????#2002-01-01#”)
          ????????????  外部數據庫1.查詢?(“select?*?from?chj?where?”?+?組合框1.內容?+?“=”?+?“#”?+?
          ????????????查找編輯框.內容?+?“#”)
          ???????????? ?、?、也可以將SQL語句中的字段名(尤其是中文名)可用中括號括住,如:[字段名]。
          ????????????  
          ????????????  ⑷、SQL語句要用半角輸入法輸入,否則可能會出錯。
          ????????????  那么在易語言中怎樣調用SQL語句呢?一般是在外部數據庫對象(控件)的方法中調用,試概括如下:
          ???????????? ?、拧ν獠繑祿爝M行查詢的方法。
          ????????????  對外部數據庫的查詢就是在對外部數據庫不加編輯改動的前提下,只通過記錄集來對數據庫進行顯示、查詢、篩選、排序和記錄集的合并等操作。
          ????????????  所有查詢類的方法起源于下面這個語句,其他查詢類語句是對這個語句的調用(將此語句作為唯一的參數),該語句如下:
          ????????????  外部數據庫.查詢?(查詢類SQL語句)
          ????????????  也可這樣表達:
          ????????????  外部數據庫.查詢?(“SELECT...FROM...[WHERE]...[GROUP?BY]...[ORDER?BY]...?”)
          ????????????  該方法是對當前被打開數據庫進行數據查詢,返回的結果稱為“記錄集句柄”(即記錄集的標記)。注意當不再使用此記錄集時,必須使用“關閉記錄集”將其關閉,如果失敗,返回0。在易語言中,將以上語句等同于記錄集句柄以作為其他查詢類語句的參數。為了使該參數在所有子程序中都能應用,我們一般把它設置為整數型全局變量,并將其值設置如下:
          ????????????  記錄集句柄=外部數據庫.查詢?(查詢類SQL語句)
          ????????????  由于易語言要把SQL語句轉化為文本型才能調用,所以嵌入式SQL語句兩邊要有雙引號,例句:
          ????????????  記錄集句柄?=?外部數據庫1.查詢?(“select?*?from?chj?”)
          ????????????  ※?“chj”是外部數據庫中一個表的名稱
          ????????????  又如,欲得到排序的記錄集,應象下面這樣賦值:
          ????????????  記錄集句柄?=?外部數據庫1.查詢?(“SELECT?*?FROM?chj?ORDER?BY?語文?DESC”)
          ????????????  現將外部數據庫控件中其他的查詢類方法列舉如下:
          ???????????? ?、?、外部數據庫.重新查詢?(記錄集句柄)?即:
          ????????????  外部數據庫.重新查詢?(外部數據庫.查詢?(查詢類SQL語句))
          ????????????  例句:外部數據庫1.重新查詢?(外部數據庫1.查詢?(“select?*?from?chj?”))?
          ???????????? ?、?、外部數據庫.首記錄前?(記錄集句柄)?即:
          ????????????  外部數據庫.首記錄前?(外部數據庫.查詢?(查詢類SQL語句))
          ????????????  例句:外部數據庫1.首記錄前?(記錄集句柄)
          ???????????? ?、邸⑼獠繑祿欤灿涗浐?(記錄集句柄)
          ????????????  ④、外部數據庫.到首記錄?(記錄集句柄)
          ???????????? ?、?、外部數據庫.到尾記錄?(記錄集句柄)
          ???????????? ?、蕖⑼獠繑祿欤角耙挥涗?(記錄集句柄)
          ???????????? ?、?、外部數據庫.到后一記錄?(記錄集句柄)
          ???????????? ?、唷⑼獠繑祿欤x?(記錄集句柄,字段名稱或位置)
          ????????????  例句:語文編輯框.內容?=?到文本?(外部數據庫1.讀?(記錄集句柄,?“語文”))
          ???????????? ?、?、對外部數據庫進行編輯的方法。
          ????????????  所謂對外部數據庫的編輯,就是變更改動外部數據庫本身,包括添加、更新、刪除等,對數據庫進行編輯不必通過記錄集。所有非查詢類SQL語句都嵌入下面這個語句來執行:
          ????????????  外部數據庫.執行?(非查詢類SQL語句)
          ????????????  ①、添加記錄,其語法如下:
          ????????????  外部數據庫.執行?(“insert?into?表名稱(字段1,字段2...)?values?(字段值1,字段值2...)?”)
          ????????????  例句:
          ????????????  外部數據庫1.執行?(“INSERT?INTO?chj?”?+?“(學號,姓名,語文,數學,英語)”?+?“?valueS?”?+?
          ????????????“(”?+?學號編輯框.內容?+?“,'”?+?姓名編輯框.內容?+?“','”?+?語文編輯框.內容?+?“','”?+?
          ????????????數學編輯框.內容?+?“','”?+?英語編輯框.內容?+?“')”)
          ???????????? ?、?、更新記錄,其語法如下:
          ????????????  外部數據庫.執行?(“UPDATE?表名稱?SET?字段1=字段值1,字段2=字段值2...WHERE?條件式”)?
          ????????????  例句:
          ????????????  外部數據庫1.執行?(“UPDATE?chj?SET?學號=”?+?“'”?+?學號編輯框.內容?+?“',”?+?“姓名=”?
          ????????????+?“'”?+?姓名編輯框.內容?+?“',”?+?“語文=”?+?“'”?+?語文編輯框.內容?+?“',”?+?“數學=”?
          ????????????+?“'”?+?數學編輯框.內容?+?“',”?+?“英語=”?+?“'”?+?英語編輯框.內容?+?“'?”?+?“WHERE?
          ????????????姓名=”?+?“'”?+?姓名1?+?“'?”?+?“AND?語文=”?+?語文1?+?“AND?數學=”?+?數學1?+?“AND?
          ????????????英語=”?+?英語1?+?“AND?學號=”?+?學號1)
          ???????????? ?、?、刪除記錄,其語法如下:
          ????????????  外部數據庫.執行?(“DELETE?*?FROM?表名稱?WHERE?條件式”)
          ????????????  例句:
          ????????????  外部數據庫.執行?(“外部數據庫1.執行?(“DELETE?*?FROM?chj?”?+?“WHERE?姓名=”?+?“'”?+?
          ????????????姓名1?+?“'?”?+?“AND?語文=”?+?語文1?+?“AND?數學=”?+?數學1?+?“AND?英語=”?+?英語1?+?
          ????????????“AND?學號=”?+?學號1)”)
          posted @ 2007-01-19 12:17 Lansing 閱讀(1625) | 評論 (3)編輯 收藏
          Java虛擬機

          一、什么是Java虛擬機


          Java虛擬機是一個想象中的機器,在實際的計算機上通過軟件模擬來實現。Java虛擬機有自己想象中的硬件,如處理器、堆棧、寄存器等,還具有相應的指令系統。


          1.為什么要使用Java虛擬機


          Java語言的一個非常重要的特點就是與平臺的無關性。而使用Java虛擬機是實現這一特點的關鍵。一般的高級語言如果要在不同的平臺上運行,至少需要編譯成不同的目標代碼。而引入Java語言虛擬機后,Java語言在不同平臺上運行時不需要重新編譯。Java語言使用模式Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就可以在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行。


          2.誰需要了解Java虛擬機


          Java虛擬機是Java語言底層實現的基礎,對Java語言感興趣的人都應對Java虛擬機有個大概的了解。這有助于理解Java語言的一些性質,也有助于使用Java語言。對于要在特定平臺上實現Java虛擬機的軟件人員,Java語言的編譯器作者以及要用硬件芯片實現Java虛擬機的人來說,則必須深刻理解Java虛擬機的規范。另外,如果你想擴展Java語言,或是把其它語言編譯成Java語言的字節碼,你也需要深入地了解Java虛擬機。


          3.Java虛擬機支持的數據類型


          Java虛擬機支持Java語言的基本數據類型如下:


          byte://1字節有符號整數的補碼
          short://2字節有符號整數的補碼
          int://4字節有符號整數的補碼
          long://8字節有符號整數的補碼
          float://4字節IEEE754單精度浮點數
          double://8字節IEEE754雙精度浮點數
          char://2字節無符號Unicode字符


          幾乎所有的Java類型檢查都是在編譯時完成的。上面列出的原始數據類型的數據在Java執行時不需要用硬件標記。操作這些原始數據類型數據的字節碼(指令)本身就已經指出了操作數的數據類型,例如iadd、ladd、fadd和dadd指令都是把兩個數相加,其操作數類型別是int、long、float和double。虛擬機沒有給boolean(布爾)類型設置單獨的指令。boolean型的數據是由integer指令,包括integer返回來處理的。boolean型的數組則是用byte數組來處理的。虛擬機使用IEEE754格式的浮點數。不支持IEEE格式的較舊的計算機,在運行Java數值計算程序時,可能會非常慢。


          虛擬機支持的其它數據類型包括:
          object//對一個Javaobject(對象)的4字節引用
          returnAddress//4字節,用于jsr/ret/jsr-w/ret-w指令
          注:Java數組被當作object處理。


          虛擬機的規范對于object內部的結構沒有任何特殊的要求。在Sun公司的實現中,對object的引用是一個句柄,其中包含一對指針:一個指針指向該object的方法表,另一個指向該object的數據。用Java虛擬機的字節碼表示的程序應該遵守類型規定。Java虛擬機的實現應拒絕執行違反了類型規定的字節碼程序。Java虛擬機由于字節碼定義的限制似乎只能運行于32位地址空間的機器上。但是可以創建一個Java虛擬機,它自動地把字節碼轉換成64位的形式。從Java虛擬機支持的數據類型可以看出,Java對數據類型的內部格式進行了嚴格規定,這樣使得各種Java虛擬機的實現對數據的解釋是相同的,從而保證了Java的與平臺無關性和可
          移植性。


          二、Java虛擬機體系結構


          Java虛擬機由五個部分組成:一組指令集、一組寄存器、一個棧、一個無用單元收集堆(Garbage-collected-heap)、一個方法區域。這五部分是Java虛擬機的邏輯成份,不依賴任何實現技術或組織方式,但它們的功能必須在真實機器上以某種方式實現。


          1.Java指令集


          Java虛擬機支持大約248個字節碼。每個字節碼執行一種基本的CPU運算,例如,把一個整數加到寄存器,子程序轉移等。Java指令集相當于Java程序的匯編語言。
          Java指令集中的指令包含一個單字節的操作符,用于指定要執行的操作,還有0個或多個操作數,提供操作所需的參數或數據。許多指令沒有操作數,僅由一個單字節的操作符構成。


          虛擬機的內層循環的執行過程如下:


          do{
          取一個操作符字節;
          根據操作符的值執行一個動作;
          }while(程序未結束)


          由于指令系統的簡單性,使得虛擬機執行的過程十分簡單,從而有利于提高執行的效率。指令中操作數的數量和大小是由操作符決定的。如果操作數比一個字節大,那么它存儲的順序是高位字節優先。例如,一個16位的參數存放時占用兩個字節,其值為:


          第一個字節*256+第二個字節字節碼指令流一般只是字節對齊的。指令tabltch和lookup是例外,在這兩條指令內部要求強制的4字節邊界對齊。


          2.寄存器


          Java虛擬機的寄存器用于保存機器的運行狀態,與微處理器中的某些專用寄存器類似。


          Java虛擬機的寄存器有四種:
          pc:Java程序計數器。
          optop:指向操作數棧頂端的指針。
          frame:指向當前執行方法的執行環境的指針。
          vars:指向當前執行方法的局部變量區第一個變量的指針。


          Java虛擬機


          Java虛擬機是棧式的,它不定義或使用寄存器來傳遞或接受參數,其目的是為了保證指令集的簡潔性和實現時的高效性(特別是對于寄存器數目不多的處理器)。
          所有寄存器都是32位的。


          3.棧


          Java虛擬機的棧有三個區域:局部變量區、運行環境區、操作數區。


          (1)局部變量區 每個Java方法使用一個固定大小的局部變量集。它們按照與vars寄存器的字偏移量來尋址。局部變量都是32位的。長整數和雙精度浮點數占據了兩個局部變量的空間,卻按照第一個局部變量的索引來尋址。(例如,一個具有索引n的局部變量,如果是一個雙精度浮點數,那么它實際占據了索引n和n+1所代表的存儲空間。)虛擬機規范并不要求在局部變量中的64位的值是64位對齊的。虛擬機提供了把局部變量中的值裝載到操作數棧的指令,也提供了把操作數棧中的值寫入局部變量的指令。


          (2)運行環境區 在運行環境中包含的信息用于動態鏈接,正常的方法返回以及異常傳播。


          ·動態鏈接
          運行環境包括對指向當前類和當前方法的解釋器符號表的指針,用于支持方法代碼的動態鏈接。方法的class文件代碼在引用要調用的方法和要訪問的變量時使用符號。動態鏈接把符號形式的方法調用翻譯成實際方法調用,裝載必要的類以解釋還沒有定義的符號,并把變量訪問翻譯成與這些變量運行時的存儲結構相應的偏移地址。動態鏈接方法和變量使得方法中使用的其它類的變化不會影響到本程序的代碼。


          ·正常的方法返回
          如果當前方法正常地結束了,在執行了一條具有正確類型的返回指令時,調用的方法會得到一個返回值。執行環境在正常返回的情況下用于恢復調用者的寄存器,并把調用者的程序計數器增加一個恰當的數值,以跳過已執行過的方法調用指令,然后在調用者的執行環境中繼續執行下去。


          ·異常和錯誤傳播
          異常情況在Java中被稱作Error(錯誤)或Exception(異常),是Throwable類的子類,在程序中的原因是:①動態鏈接錯,如無法找到所需的class文件。②運行時錯,如對一個空指針的引用


          ·程序使用了throw語句。
          當異常發生時,Java虛擬機采取如下措施:
          ·檢查與當前方法相聯系的catch子句表。每個catch子句包含其有效指令范圍,能夠處理的異常類型,以及處理異常的代碼塊地址。
          ·與異常相匹配的catch子句應該符合下面的條件:造成異常的指令在其指令范圍之內,發生的異常類型是其能處理的異常類型的子類型。如果找到了匹配的catch子句,那么系統轉移到指定的異常處理塊處執行;如果沒有找到異常處理塊,重復尋找匹配的catch子句的過程,直到當前方法的所有嵌套的catch子句都被檢查過。
          ·由于虛擬機從第一個匹配的catch子句處繼續執行,所以catch子句表中的順序是很重要的。因為Java代碼是結構化的,因此總可以把某個方法的所有的異常處理器都按序排列到一個表中,對任意可能的程序計數器的值,都可以用線性的順序找到合適的異常處理塊,以處理在該程序計數器值下發生的異常情況。
          ·如果找不到匹配的catch子句,那么當前方法得到一個"未截獲異常"的結果并返回到當前方法的調用者,好像異常剛剛在其調用者中發生一樣。如果在調用者中仍然沒有找到相應的異常處理塊,那么這種錯誤傳播將被繼續下去。如果錯誤被傳播到最頂層,那么系統將調用一個缺省的異常處理塊。
          (3)操作數棧區 機器指令只從操作數棧中取操作數,對它們進行操作,并把結果返回到棧中。選擇棧結構的原因是:在只有少量寄存器或非通用寄存器的機器(如Intel486)上,也能夠高效地模擬虛擬機的行為。操作數棧是32位的。它用于給方法傳遞參數,并從方法接收結果,也用于支持操作的參數,并保存操作的結果。例如,iadd指令將兩個整數相加。相加的兩個整數應該是操作數棧頂的兩個字。這兩個字是由先前的指令壓進堆棧的。這兩個整數將從堆棧彈出、相加,并把結果壓回到操作數棧中。


          每個原始數據類型都有專門的指令對它們進行必須的操作。每個操作數在棧中需要一個存儲位置,除了long和double型,它們需要兩個位置。操作數只能被適用于其類型的操作符所操作。例如,壓入兩個int類型的數,如果把它們當作是一個long類型的數則是非法的。在Sun的虛擬機實現中,這個限制由字節碼驗證器強制實行。但是,有少數操作(操作符dupe和swap),用于對運行時數據區進行操作時是不考慮類型的。


          4.無用單元收集堆


          Java的堆是一個運行時數據區,類的實例(對象)從中分配空間。Java語言具有無用單元收集能力:它不給程序員顯式釋放對象的能力。Java不規定具體使用的無用單元收集算法,可以根據系統的需求使用各種各樣的算法。


          5.方法區


          方法區與傳統語言中的編譯后代碼或是Unix進程中的正文段類似。它保存方法代碼(編譯后的java代碼)和符號表。在當前的Java實現中,方法代碼不包括在無用單元收集堆中,但計劃在將來的版本中實現。每個類文件包含了一個Java類或一個Java界面的編譯后的代碼??梢哉f類文件是Java語言的執行代碼文件。為了保證類文件的平臺無關性,Java虛擬機規范中對類文件的格式也作了詳細的說明。其具體細節請參考Sun公司的Java虛擬機規范。

          posted @ 2007-01-18 14:27 Lansing 閱讀(591) | 評論 (1)編輯 收藏
          Sun 提供的標準 Java 開發包(JDK)沒有提供創建特定于平臺的可執行文件的工具(一點都不吃驚,這是真的)。然而,其實有很多方法能夠幫助你實現這一想法。
            
            第三方工具
            一種方法是使用第三方商業工具或免費工具將 Java 應用程序打包為一個可執行文件。
            
            下面是價格和特性都不同的兩個工具,但是在 Web 上還有其它幾個第三方工具可以免費下載。
            
            http://www.bysoft.se/sureshot/exej/
            http://www.duckware.com/jexepack/
            使用商業安裝程序(installer)
            InstallAnywhere 是一個常用的安裝程序,它將管理應用程序的安裝過程,并將應用程序打包為可執行程序。
            
            使用 .jar
            除了以上方法之外,還可以將應用程序打包為一個可執行的 .jar 文件,而不是一個 .exe 文件。在這篇文章中我將不詳細介紹這種方法,你可以在這里找到一個非常棒的在線教程
            
            你需要做的最重要的一件事是指定在 .jar 文件中哪個類是應用程序的入口點。例如,對你的應用程序來說就是具有一個 public static void main(String[] args) 方法的引導類??梢栽?.jar 表示文件的 Main-Class 頭部信息中提供這些信息。這個頭部信息的通用形式為:Main-Class: classname,其中 classname 是應用程序的入口點的類名稱。
            
            使用 Java Webstart
            Java Webstart 是標準 Java 運行時環境(JRE)的隱藏的寶物,自從版本 1.3 開始,JRE 就包含了 Java Webstart。它是一個簡單但功能強大且靈活的將應用程序部署到任何平臺的方法。
            
            Webstart 允許應用程序的用戶從他們的瀏覽器、電子郵件或桌面啟動和管理應用程序。Java Webstart 的一個主要優點是一旦應用程序被安裝,在每次啟動它時,它都將會檢查用戶是否在運行最新版本的應用程序。如果不是,應用程序將通過網絡裝載新版本到桌面然后執行,因此解決了軟件傳播問題。
            
            如果你的應用程序已經有很多用戶的話,這一點就尤其重要。還有很重要的一點是,它能夠檢查用戶的本地桌面環境,并能保證他們安裝了正確的 JRE 版本來運行你的應用程序。
            
            Java Webstart 本身有一系列文章,所以我建議你訪問 Java Webstart Web 站點查看更多文檔和教程。
            
            結束語
            前兩種方法可能會滿足你對這個問題的需要,但是我強烈建議你仔細看一下 Java Webstart。它是 Java 標準的一部分,并且能夠在所有平臺下一致工作。我比較喜歡這個應用程序打包方法。
          posted @ 2007-01-18 14:21 Lansing 閱讀(703) | 評論 (0)編輯 收藏
               摘要: Lucene In Action ch 6(I) 筆記 --自定義排序 ----- 2006-2-16?????? 使用 Lucene 來搜索內容,搜索結果的顯示順序當然是比較重要的.Lucene中Build-in的幾個排序定義在大多數情況下是不適合我們使用的.要適合自己的應用程序的場景,就只能自定義排序功能,本節...  閱讀全文
          posted @ 2007-01-05 10:27 Lansing 閱讀(728) | 評論 (0)編輯 收藏
               摘要: Lucene In Action ch 5 筆記 --高級搜索技術 ----- 2006-2-15 該章介紹了Lucene的一些高級技術,如 結果排序,搜索多個Index,過慮技術....下面就看看這些高級技巧吧. I.Sorting search results ...  閱讀全文
          posted @ 2007-01-05 10:25 Lansing 閱讀(613) | 評論 (0)編輯 收藏
               摘要: Lucene In Action ch 4 筆記(I) -- Analysis ----- 2006-2-12 本章詳細的討論了 Lucene的分析處理過程和幾個Analyzer. 在indexing過程中要把需要indexing的text分析處理一下, 經過處理和切詞 然后建立index. 而不通的Ana...  閱讀全文
          posted @ 2007-01-05 10:14 Lansing 閱讀(1094) | 評論 (0)編輯 收藏
               摘要: 1. 實現一個簡單的search feature ?? 在本章中只限于討論簡單Lucene 搜索API, 有下面幾個相關的類: ?Lucene 基本搜索API: 類 ...  閱讀全文
          posted @ 2007-01-05 10:11 Lansing 閱讀(845) | 評論 (0)編輯 收藏
               摘要: Lucene In Action ch2 系統的講解了 indexing,下面就來看看吧. 1,indexing 的處理過程. ? 首先要把indexing的數據轉換為text,因為Lucene只能索引text,然后由Analysis來過慮text,把一些ch1中提到的所謂的stop words 過濾掉, 然后建...  閱讀全文
          posted @ 2007-01-05 10:10 Lansing 閱讀(841) | 評論 (0)編輯 收藏

          若人生是直線前進的,
          那么命中注定有若干的交點,
          認識注定的人,
          欣賞注定的風景...

          可人生還是有選擇的,
          那么道路也就多了些分叉口,
          錯過注定的人,
          錯過注定的風景...

          若我曾經再某個分叉路口選錯了方向卻遇到了注定的人,該感謝上蒼賜予我的福氣吧!
          可是人生又有了新的岔口,選擇有些艱難,但是面對幸福我很堅定!

          該怎么愛你

          我聽 過你的微笑
          就忘了 所有動蕩
          當我靠過你的 那雙肩膀
          也就忘了 塵土飛楊
          我只是 一棵小草
          孤單的 微不足道
          當你搬進我的小小國度
          我才相信 平凡的美好
          該怎么愛你 我才不會忘
          你的溫度 來過身旁
          就算哪一天 失去了方向
          愛過的 完整的 還在心上
          該怎么愛你 才可以盼望
          那種幸福 遠遠流長
          就怕這時間 讓我趕不上
          說一句 只一句 我曾到過天堂
          我相信最燦爛的一秒
          是守著你的眼光
          不是熱烈擁抱
          不是驚濤駭浪
          我相信最美麗的風光
          是在彼此身旁
          有另一雙肩膀
          一起慢慢變老

          posted @ 2006-12-13 14:22 Lansing 閱讀(317) | 評論 (0)編輯 收藏
          ?本文主要面向具體使用,適用于已熟悉java編程的lucene初學者。
          1. Lucene的簡介


          1.1 Lucene 歷史


          ????? org.apache.lucene包是純java語言的全文索引檢索工具包。
          ????? Lucene的作者是資深的全文索引/檢索專家,最開始發布在他本人的主頁上,2001年10月貢獻給APACHE,成為APACHE基金jakarta的一個子項目。
          ????? 目前,lucene廣泛用于全文索引/檢索的項目中。
          ????? lucene也被翻譯成C#版本,目前發展為Lucene.Net(不過最近好象有流產的消息)。


          1.2 Lucene 原理


          ?????? lucene的檢索算法屬于索引檢索,即用空間來換取時間,對需要檢索的文件、字符流進行全文索引,在檢索的時候對索引進行快速的檢索,得到檢索位置,這個位置記錄檢索詞出現的文件路徑或者某個關鍵詞。
          ?????? 在使用數據庫的項目中,不使用數據庫進行檢索的原因主要是:數據庫在非精確查詢的時候使用查詢語言“like %keyword%”,對數據庫進行查詢是對所有記錄遍歷,并對字段進行“%keyword%”匹配,在數據庫的數據龐大以及某個字段存儲的數據量龐大的時候,這種遍歷是致命的,它需要對所有的記錄進行匹配查詢。因此,lucene主要適用于文檔集的全文檢索,以及海量數據庫的模糊檢索,特別是對數據庫的xml或者大數據的字符類型。


          2.Lucene的下載和配置


          2.1 Lucene的下載


          ?????? lucene在jakarta項目中的發布主頁:http://jakarta.apache.org/lucene/docs/index.html。以下主要針對windows用戶,其它用戶請在上面的地址中查找相關下載。


          ?????? lucene的.jar包的下載(包括.jar和一個范例demo):
          http://apache.oregonstate.edu/jakarta/lucene/binaries/lucene-1.4-final.zip


          ??????? lucene的源代碼下載:
          http://www.signal42.com/mirrors/apache/jakarta/lucene/source/lucene-1.4-final-src.zip


          ?lucene的api地址:http://jakarta.apache.org/lucene/docs/api/index.html


          ?本文使用lucene版本:lucene-1.4-final.jar。


          2.2 lucene的配置


          ??????? 首先請確定你的機子已經進行了java使用環境的基本配置,即確保在某個平臺下能夠運行java源代碼,否則請查閱相關文檔進行配置。
          ??????? 接下來進入lucene的配置:
          ??????? 普通使用者:在環境變量的CLASSPATH中添加lucene的位置。比如:“D:\java \lucene-1.4-final\lucene-1.4-final.jar;”。
          ?????? jbuilder使用者:在“Project”--“Project Properties”--“Required Libraries”進行添加。
          ?????? Jsp使用者:也可以直接將lucene-1.4-final.jar文件放到\WEB-INF\classes下。


          3. Lucene 的范例(Demo )


          3.1 Demo說明

          ?????
          ??????? 可以得到的Demo包括:lucene-demos-1.4-final、XMLIndexingDemo,lucene-demos-1.4-final中包括對普通文件和html文件的兩種索引,XMLIndexingDemo針對xml文件的索引。他們的區別主要在于:對普通文件進行索引時只要對文件的全文進行索引,而針對html、xml文件時,對標簽類型不能進行索引,在實現上:html、xml的索引需要額外的數據流分析器,以分析哪些內容有用哪些無用。因此,在后兩者實現上,索引的時間額外開支,甚至超過索引本身時間,而檢索時間沒有區別。


          ??????? 以上Demo中,lucene-demos-1.4-final自帶于lucene-1.4-final.zip中,XMLIndexingDemo的下載地址:
          http://cvs.apache.org/viewcvs.cgi/jakarta-lucene-sandbox/contributions/XML-Indexing-Demo/


          3.2 Demo的運行


          ????????首先將demo.jar的路徑添加如環境變量的CLASSPATH中,例如:“D:\java\lucene-1.4-final\lucene-demos-1.4-final.jar;”,同時確保已經添加lucene-1.4-final.jar。


          ????????然后進行文件的全文索引,在dos控制臺中,輸入命令“java org.apache.lucene.demo.IndexFiles {full-path-to-lucene}/src”,后面的路徑為所要進行索引的文件夾,例如:“java org.apache.lucene.demo.IndexFiles c:\test”。


          ??????? 接著對索引進行檢索,敲入“java org.apache.lucene.demo.SearchFiles”,在提示“Query:”后輸入檢索詞,程序將進行檢索列出檢索得到的結果(檢索詞出現的文件路徑)。
          ?
          ?????? 其他Demo的運行請參考\docs\demo.html。
          ?????? 在運行Demo后請閱讀Demo的源代碼以便深入學習。

          4. 利用Lucene進行索引


          ??????? 進行lucene的熟悉后,我們將學習如何使用Lucene。
          ?一段索引的應用實例:

          ??? //需要捕捉IOException異常
          ??? //建立一個IndexWriter,索引保存目錄為“index”
          ??? String[] stopStrs = {
          ??????? "他奶奶的", "fuck"};
          ??? StandardAnalyzer analyzer = new StandardAnalyzer(stopStrs);
          ??? IndexWriter writer = new IndexWriter("index", analyzer, true);
          ???
          ??? //添加一條文檔
          ??? Document doc = new Document();
          ??? doc.add(Field.UnIndexed("id", "1"));//“id”為字段名,“1”為字段值
          ??? doc.add(Field.Text("text", "fuck,他奶奶的,入門與使用"));
          ??? writer.addDocument(doc);
          ???
          ??? //索引完成后的處理
          ??? writer.optimize();
          ??? writer.close();

          ?????? 看完這段實例后,我們開始熟悉lucene的使用:

          4.1 Lucene的索引接口


          ?在學習索引的時候,首先需要熟悉幾個接口:


          4.1.1分析器Analyzer


          ??????? 分析器主要工作是篩選,一段文檔進來以后,經過它,出去的時候只剩下那些有用的部分,其他則剔除。而這個分析器也可以自己根據需要而編寫。
          ??????? org.apache.lucene.analysis.Analyzer:這是一個虛構類,以下兩個借口均繼承它而來。


          ????????org.apache.lucene.analysis.SimpleAnalyzer:分析器,支持最簡單拉丁語言。


          ????????org.apache.lucene.analysis.standard.StandardAnalyzer:標準分析器,除了拉丁語言還支持亞洲語言,并在一些匹配功能上進行完善。在這個接口中還有一個很重要的構造函數:StandardAnalyzer(String[] stopWords),可以對分析器定義一些使用詞語,這不僅可以免除檢索一些無用信息,而且還可以在檢索中定義禁止的政治性、非法性的檢索關鍵詞。


          4.1.2 IndexWriter


          ????????IndexWriter的構造函數有三種接口,針對目錄Directory、文件File、文件路徑String三種情況。
          例如IndexWriter(String path, Analyzer a, boolean create),path為文件路徑,a為分析器,create標志是否重建索引(true:建立或者覆蓋已存在的索引,false:擴展已存在的索引。)
          ?????? 一些重要的方法:

          接口名

          備注

          addDocument(Document doc)

          索引添加一個文檔

          addIndexes(Directory[] dirs)

          將目錄中已存在索引添加到這個索引

          addIndexes(IndexReader[] readers)

          將提供的索引添加到這個索引

          optimize()

          合并索引并優化

          close()

          關閉


          ?????? IndexWriter為了減少大量的io維護操作,在每得到一定量的索引后建立新的小索引文件(筆者測試索引批量的最小單位為10),然后再定期將它們整合到一個索引文件中,因此在索引結束時必須進行wirter. optimize(),以便將所有索引合并優化。


          4.1.3 org.apache.lucene.document


          ?以下介紹兩種主要的類:
          ?a)org.apache.lucene.document.Document:
          ????????Document文檔類似數據庫中的一條記錄,可以由好幾個字段(Field)組成,并且字段可以套用不同的類型(詳細見b)。Document的幾種接口:
          ?

          接口名

          備注

          add(Field field)

          添加一個字段(Field)到Document

          String get(String name)

          從文檔中獲得一個字段對應的文本

          Field getField(String name)

          由字段名獲得字段值

          Field[] getFields(String name)

          由字段名獲得字段值的集


          ?b)org.apache.lucene.document.Field
          ??????? 即上文所說的“字段”,它是Document的片段section。
          ??????? Field的構造函數:
          ?????? Field(String name, String string, boolean store, boolean index, boolean token)。
          ??????? Indexed:如果字段是Indexed的,表示這個字段是可檢索的。
          ????????Stored:如果字段是Stored的,表示這個字段的值可以從檢索結果中得到。
          ????????Tokenized:如果一個字段是Tokenized的,表示它是有經過Analyzer轉變后成為一個tokens序列,在這個轉變過程tokenization中,Analyzer提取出需要進行索引的文本,而剔除一些冗余的詞句(例如:a,the,they等,詳見org.apache.lucene.analysis.StopAnalyzer.ENGLISH_STOP_WORDS和org.apache.lucene.analysis.standard.StandardAnalyzer(String[] stopWords)的API)。Token是索引時候的基本單元,代表一個被索引的詞,例如一個英文單詞,或者一個漢字。因此,所有包含中文的文本都必須是Tokenized的。
          ???? Field的幾種接口:

          Name

          Stored

          Indexed

          Tokenized

          use

          Keyword(String name,

          ??????? String value)

          Y

          Y

          N

          date,url

          Text(String name, Reader value)

          N

          Y

          Y

          short text fields:

          title,subject

          Text(String name, String value)

          Y

          Y

          Y

          longer text fields,

          like “body”

          UnIndexed(String name,

          String value)

          Y

          N

          N

          ?

          UnStored(String name,

          ???????? String value)

          N

          Y

          Y

          ?

          ?


          5. 利用Lucene進行檢索


          5.1 一段簡單的檢索代碼

          ?

          ??? //需要捕捉IOException,ParseException異常
          ??? //處理檢索條件
          ??? Query query = QueryParser.parse("入門", "text", analyzer);

          ??? //檢索
          ??? Searcher searcher = new IndexSearcher("./index");//"index"指定索引文件位置
          Hits hits = searcher.search(query);

          ??? //打印結果值集
          ??? for (int i = 0; i < hits.length(); i++) {
          ????? doc = hits.doc(i);
          ????? String id = doc.get("id");
          ????? System.out.println("found " + "入門" + " on the id:" + id);
          }

          ?

          5.2 利用Lucene的檢索接口


          5.2.1 Query與QueryParser


          ??????? 主要使用方法:
          QueryParser .parse(String query, String field, Analyzer analyzer),例如:
          Query query = QueryParser.parse("入門", "text", analyzer);
          "入門"為檢索詞, "text"為檢索的字段名, analyzer為分析器


          5.2.2 Hits與Searcher


          ?????? Hits的主要使用接口:
          ?

          接口名

          備注

          Doc(int n)

          返回第n個的文檔的所有字段

          length()

          返回這個集中的可用個數

          ?


          6. Lucene的其他使用


          6.1 Lucene 的索引修改


          ??????? 下面給出一段修改索引的代碼,請根據Lucene的API解讀:


          ? /**
          ?? * 對已有的索引添加新的一條索引
          ?? * @param idStr String:要修改的id
          ?? * @param doc Document:要修改的值
          ?? */
          ? public void addIndex(String idStr, String valueStr) {
          ??? StandardAnalyzer analyzer = new StandardAnalyzer();
          ??? IndexWriter writer = null;
          ??? try {
          ????? writer = new IndexWriter(indexPath, analyzer, false);
          ????? writer.mergeFactor = 2; //修正lucene 1.4.2 bug,不添加則不合并原有索引

          ?????? ?? Document doc = new Document();
          ????????? doc.add(Field.UnIndexed("id", idStr));//“id”為字段名,“1”為字段值
          ????????? doc.add(Field.Text("text", valueStr));
          ????? writer.addDocument(doc);

          ????? writer.optimize();
          ????? writer.close();
          ??? }
          ??? catch (IOException ioe) {
          ????? ioe.printStackTrace();
          ??? }
          ? }

          ? /**
          ?? * 刪除索引
          ?? *
          ?? * @param idStr String
          ?? */
          ? public void deleteIndex(String idStr) {
          ??? try {
          ????? Directory dirt = FSDirectory.getDirectory(indexPath, false);
          ????? IndexReader reader = IndexReader.open(dirt);
          ????? IndexXML.deleteIndex(idStr, reader);
          ????? reader.close();
          ????? dirt.close();
          ??? }
          ??? catch (IOException ioe) {
          ????? ioe.printStackTrace();
          ??? }
          ? }


          6.2 Lucene 的檢索結果排序


          ??????? Lucene的排序主要是對org.apache.lucene.search.Sort的使用。Sort可以直接根據字段Field生成,也可以根據標準的SortField生成,但是作為Sort的字段,必須符合以下的條件:唯一值以及Indexed??梢詫ntegers, Floats, Strings三種類型排序。
          ??????? 對整數型的ID檢索結果排序只要進行以下的簡單操作:

          ?Sort sort = new Sort("id");
          Hits hits = searcher.search(query, sort);

          ?????? 用戶還可以根據自己定義更加復雜的排序,詳細請參考API。


          7 總結


          ??????? Lucene給java的全文索引檢索帶來了非常強大的力量,以上僅對Lucene進行簡單的入門說明。

          posted @ 2006-11-08 14:59 Lansing 閱讀(349) | 評論 (0)編輯 收藏

          Lucene提供了方便您創建自建查詢的API,也通過QueryParser提供了強大的查詢語言。

          本文講述Lucene的查詢語句解析器支持的語法,Lucene的查詢語句解析器是使用JavaCC工

          具生成的詞法解析器,它將查詢字串解析為Lucene Query對象。
          項(Term)
          一條搜索語句被拆分為一些項(term)和操作符(operator)。項有兩種類型:單獨項和

          短語。
          單獨項就是一個單獨的單詞,例如"test" , "hello"。
          短語是一組被雙引號包圍的單詞,例如"hello dolly"。
          多個項可以用布爾操作符連接起來形成復雜的查詢語句(接下來您就會看到)。
          注意:Analyzer建立索引時使用的解析器和解析單獨項和短語時的解析器相同,因此選擇

          一個不會受查詢語句干擾的Analyzer非常重要。luence1.4的StandardAnalyzer的解析器已

          經支持中文等亞洲國家的文字了,可以直接。標準的解析其不支持中文。

          域(Field)
          Lucene支持域。您可以指定在某一個域中搜索,或者就使用默認域。域名及默認域是具體

          索引器實現決定的。(怎么定制默認域?)
          您可以這樣搜索域:域名+":"+搜索的項名。
          舉個例子,假設某一個Lucene索引包含兩個域,title和text,text是默認域。如果您想查

          找標題為"The Right Way"且含有"don't go this way"的文章,您可以輸入:
          title:"The Right Way" AND text:go
          或者
          title:"Do it right" AND right
          因為text是默認域,所以這個域名可以不行。
          注意:域名只對緊接于其后的項生效,所以
          title:Do it right
          只有"Do"屬于title域。"it"和"right"仍將在默認域中搜索(這里是text域)。

          項修飾符(Term Modifiers)
          Lucene支持項修飾符以支持更寬范圍的搜索選項。
          用通配符搜索
          Lucene支持單個與多個字符的通配搜索。
          使用符號"?"表示單個任意字符的通配。
          使用符號"*"表示多個任意字符的通配。
          單個任意字符匹配的是所有可能單個字符。例如,搜索"text或者"test",可以這樣:

          te?t
          多個任意字符匹配的是0個及更多個可能字符。例如,搜索test, tests 或者 tester,可

          以這樣: test*
          您也可以在字符竄中間使用多個任意字符通配符。 te*t
          注意:您不能在搜索的項開始使用*或者?符號。

          模糊查詢
          Lucene支持基于Levenshtein Distance與Edit Distance算法的模糊搜索。要使用模糊搜索

          只需要在單獨項的最后加上符號"~"。例如搜索拼寫類似于"roam"的項這樣寫:
          roam~
          這次搜索將找到形如foam和roams的單詞。
          注意:使用模糊查詢將自動得到增量因子(boost factor)為0.2的搜索結果.

          鄰近搜索(Proximity Searches)
          Lucene還支持查找相隔一定距離的單詞。鄰近搜索是在短語最后加上符號"~"。例如在文檔

          中搜索相隔10個單詞的"apache"和"jakarta",這樣寫: "jakarta apache"~10

          Boosting a Term
          Lucene provides the relevance level of matching documents based on the terms

          found. To boost a term use the caret, "^", symbol with a boost factor (a

          number) at the end of the term you are searching. The higher the boost factor,

          the more relevant the term will be.
          Lucene可以設置在搜索時匹配項的相似度。在項的最后加上符號"^"緊接一個數字(增量值

          ),表示搜索時的相似度。增量值越高,搜索到的項相關度越好。
          Boosting allows you to control the relevance of a document by boosting its

          term. For example, if you are searching for jakarta apache and you want the

          term "jakarta" to be more relevant boost it using the ^ symbol along with the

          boost factor next to the term. You would type:
          通過增量一個項可以控制搜索文檔時的相關度。例如如果您要搜索jakarta apache,同時

          您想讓"jakarta"的相關度更加好,那么在其后加上"^"符號和增量值,也就是您輸入:
          jakarta^4 apache
          This will make documents with the term jakarta appear more relevant. You can

          also boost Phrase Terms as in the example:
          這將使得生成的doucment盡可能與jakarta相關度高。您也可以增量短語,象以下這個例子

          一樣:
          "jakarta apache"^4 "jakarta lucene"

          By default, the boost factor is 1. Although, the boost factor must be positive,

          it can be less than 1 (i.e. .2)
          默認情況下,增量值是1。增量值也可以小于1(例如0.2),但必須是有效的。

          布爾操作符
          布爾操作符可將項通過邏輯操作連接起來。Lucene支持AND, "+", OR, NOT 和 "-"這些操

          作符。(注意:布爾操作符必須全部大寫)

          OR
          OR操作符是默認的連接操作符。這意味著如果兩個項之間沒有布爾操作符,就是使用OR操

          作符。OR操作符連接兩個項,意味著查找含有任意項的文檔。這與集合并運算相同。符號

          ||可以代替符號OR。
          搜索含有"jakarta apache" 或者 "jakarta"的文檔,可以使用這樣的查詢:
          "jakarta apache" jakarta 或者 "jakarta apache" OR jakarta

          AND
          AND操作符匹配的是兩項同時出現的文檔。這個與集合交操作相等。符號&&可以代替符號

          AND。
          搜索同時含有"jakarta apache" 與 "jakarta lucene"的文檔,使用查詢:
          "jakarta apache" AND "jakarta lucene"

          +
          "+"操作符或者稱為存在操作符,要求符號"+"后的項必須在文檔相應的域中存在。
          搜索必須含有"jakarta",可能含有"lucene"的文檔,使用查詢:
          +jakarta apache

          NOT
          NOT操作符排除那些含有NOT符號后面項的文檔。這和集合的差運算相同。符號!可以代替

          符號NOT。
          搜索含有"jakarta apache",但是不含有"jakarta lucene"的文檔,使用查詢:
          "jakarta apache" NOT "jakarta lucene"
          注意:NOT操作符不能單獨與項使用構成查詢。例如,以下的查詢查不到任何結果:
          NOT "jakarta apache"

          -
          "-"操作符或者禁止操作符排除含有"-"后面的相似項的文檔。
          搜索含有"jakarta apache",但不是"jakarta lucene",使用查詢:
          "jakarta apache" -"jakarta lucene"

          分組(Grouping)
          Lucene支持使用圓括號來組合字句形成子查詢。這對于想控制查詢布爾邏輯的人十分有用


          搜索含有"jakarta"或者"apache",同時含有"website"的文檔,使用查詢:
          (jakarta OR apache) AND website
          這樣就消除了歧義,保證website必須存在,jakarta和apache中之一也存在。
          轉義特殊字符(Escaping Special Characters)
          Lucene支持轉義特殊字符,因為特殊字符是查詢語法用到的。現在,特殊字符包括
          + - && || ! ( ) { } [ ] ^ " ~ * ? : \
          轉義特殊字符只需在字符前加上符號\,例如搜索(1+1):2,使用查詢
          \(1\+1\)\:2??
          (李宇翻譯,來自Lucene的幫助文檔)上面這段看了之后很有幫助,解除了使用中的不少

          疑惑,謝謝翻譯者,同時應該看到,有的時候詳細查看使用幫助文檔是非常有用的。
          ------------------------------------------------------------------------------
          索引文件格式

          本文定義了Lucene(版本1.3)用到的索引文件的格式。
          Jakarta Lucene是用Java寫成的,同時有很多團體正在默默的用其他的程序語言來改寫它

          。如果這些新的版本想和Jakarta Lucene兼容,就需要一個與具體語言無關的Lucene索引

          文件格式。本文正是試圖提供一個完整的與語言無關的Jakarta Lucene 1.3索引文件格式

          的規格定義。
          隨著Lucene不斷發展,本文也應該更新。不同語言寫成的Lucene實現版本應當盡力遵守文

          件格式,也必須產生本文的新版本。
          本文同時提供兼容性批注,描述文件格式上與前一版本不同的地方。

          定義
          Lucene中最基礎的概念是索引(index),文檔(document),域(field)和項(term)


          索引包含了一個文檔的序列。
          · 文檔是一些域的序列。
          · 域是一些項的序列。
          · 項就是一個字串。
          存在于不同域中的同一個字串被認為是不同的項。因此項實際是用一對字串表示的,第一

          個字串是域名,第二個是域中的字串。

          倒排索引
          為了使得基于項的搜索更有效率,索引中項是靜態存儲的。Lucene的索引屬于索引方式中

          的倒排索引,因為對于一個項這種索引可以列出包含它的文檔。這剛好是文檔與項自然聯

          系的倒置。

          域的類型
          Lucene中,域的文本可能以逐字的非倒排的方式存儲在索引中。而倒排過的域稱為被索引

          過了。域也可能同時被存儲和被索引。
          域的文本可能被分解許多項目而被索引,或者就被用作一個項目而被索引。大多數的域是

          被分解過的,但是有些時候某些標識符域被當做一個項目索引是很有用的。

          段(Segment)
          Lucene索引可能由多個子索引組成,這些子索引成為段。每一段都是完整獨立的索引,能

          被搜索。索引是這樣作成的:
          1. 為新加入的文檔創建新段。
          2. 合并已經存在的段。
          搜索時需要涉及到多個段和/或者多個索引,每一個索引又可能由一些段組成。

          文檔號(Document Number)
          內部的來說,Lucene用一個整形(interger)的文檔號來指示文檔。第一個被加入到索引

          中的文檔就是0號,順序加入的文檔將得到一個由前一個號碼遞增而來的號碼。
          注意文檔號是可能改變的,所以在Lucene外部存儲這些號碼時必須小心。特別的,號碼的

          改變的情況如下:
          · 只有段內的號碼是相同的,不同段之間不同,因而在一個比段廣泛的上下文環境中使用

          這些號碼時,就必須改變它們。標準的技術是根據每一段號碼多少為每一段分配一個段號

          。將段內文檔號轉換到段外時,加上段號。將某段外的文檔號轉換到段內時,根據每段中

          可能的轉換后號碼范圍來判斷文檔屬于那一段,并減調這一段的段號。例如有兩個含5個文

          檔的段合并,那么第一段的段號就是0,第二段段號5。第二段中的第三個文檔,在段外的

          號碼就是8。
          · 文檔刪除后,連續的號碼就出現了間斷。這可以通過合并索引來解決,段合并時刪除的

          文檔相應也刪掉了,新合并而成的段并沒有號碼間斷。

          緒論
          索引段維護著以下的信息:
          · 域集合。包含了索引中用到的所有的域。
          · 域值存儲表。每一個文檔都含有一個“屬性-值”對的列表,屬性即為域名。這個列表

          用來存儲文檔的一些附加信息,如標題,url或者訪問數據庫的一個ID。在搜索時存儲域的

          集合可以被返回。這個表以文檔號標識。
          · 項字典。這個字典含有所有文檔的所有域中使用過的的項,同時含有使用過它的文檔的

          文檔號,以及指向使用頻數信息和位置信息的指針。
          · 項頻數信息。對于項字典中的每個項,這些信息包含含有這個項的文檔的總數,以及每

          個文檔中使用的次數。
          · 項位置信息。對于項字典中的每個項,都存有在每個文檔中出現的各個位置。
          · Normalization factors. For each field in each document, a value is stored

          that is multiplied into the score for hits on that field. 標準化因子。對于文檔

          中的每一個域,存有一個值,用來以后乘以這個這個域的命中數(hits)。
          · 被刪除的文檔信息。這是一個可選文件,用來表明那些文檔已經刪除了。
          接下來的各部分部分詳細描述這些信息。

          文件的命名(File Naming)
          同屬于一個段的文件擁有相同的文件名,不同的擴展名。擴展名由以下討論的各種文件格

          式確定。
          一般來說,一個索引存放一個目錄,其所有段都存放在這個目錄里,盡管我們不要求您這

          樣做。

          基本數據類型(Primitive Types)

          Byte
          最基本的數據類型就是字節(byte,8位)。文件就是按字節順序訪問的。其它的一些數據

          類型也定義為字節的序列,文件的格式具有字節意義上的獨立性。

          UInt32
          32位無符號整數,由四個字節組成,高位優先。

          UInt32 --> <Byte>4
          Uint64
          64位無符號整數,由八字節組成,高位優先。

          UInt64 --> <Byte>8
          VInt
          可變長的正整數類型,每字節的最高位表明還剩多少字節。每字節的低七位表明整數的值

          。因此單字節的值從0到127,兩字節值從128到16,383,等等。

          VInt 編碼示例
          Value
          First byte
          Second byte
          Third byte

          0
          00000000
          1
          00000001
          2
          00000010
          ...
          127
          01111111
          128
          10000000
          00000001
          129
          10000001
          00000001
          130
          10000010
          00000001
          ...
          16,383
          11111111
          01111111
          16,384
          10000000
          10000000
          00000001
          16,385
          10000001
          10000000
          00000001
          ...

          這種編碼提供了一種在高效率解碼時壓縮數據的方法。

          Chars
          Lucene輸出UNICODE字符序列,使用標準UTF-8編碼。

          String
          Lucene輸出由VINT和字符串組成的字串,VINT表示字串長,字符串緊接其后。
          String --> VInt, Chars

          索引包含的文件(Per-Index Files)
          這部分介紹每個索引包含的文件。

          Segments文件
          索引中活動的段存儲在Segments文件中。每個索引只能含有一個這樣的文件,名

          為"segments".這個文件依次列出每個段的名字和每個段的大小。
          Segments --> SegCount, <SegName, SegSize>SegCount
          SegCount, SegSize --> UInt32
          SegName --> String
          SegName表示該segment的名字,同時作為索引其他文件的前綴。
          SegSize是段索引中含有的文檔數。

          Lock文件
          有一些文件用來表示另一個進程在使用索引。
          · 如果存在"commit.lock"文件,表示有進程在寫"segments"文件和刪除無用的段索引文

          件,或者表示有進程在讀"segments"文件和打開某些段的文件。在一個進程在讀

          取"segments"文件段信息后,還沒來得及打開所有該段的文件前,這個Lock文件可以防止

          另一個進程刪除這些文件。
          · 如果存在"index.lock"文件,表示有進程在向索引中加入文檔,或者是從索引中刪除文

          檔。這個文件防止很多文件同時修改一個索引。

          Deleteable文件
          名為"deletetable"的文件包含了索引不再使用的文件的名字,這些文件可能并沒有被實際

          的刪除。這種情況只存在與Win32平臺下,因為Win32下文件仍打開時并不能刪除。
          Deleteable --> DelableCount, <DelableName>DelableCount
          DelableCount --> UInt32
          DelableName --> String

          段包含的文件(Per-Segment Files)
          剩下的文件是每段中包含的文件,因此由后綴來區分。
          域(Field)
          域集合信息(Field Info)
          所有域名都存儲在這個文件的域集合信息中,這個文件以后綴.fnm結尾。
          FieldInfos (.fnm) --> FieldsCount, <FieldName, FieldBits>FieldsCount
          FieldsCount --> VInt
          FieldName --> String
          FieldBits --> Byte
          目前情況下,FieldBits只有使用低位,對于已索引的域值為1,對未索引的域值為0。
          文件中的域根據它們的次序編號。因此域0是文件中的第一個域,域1是接下來的,等等。

          這個和文檔號的編號方式相同。
          域值存儲表(Stored Fields)
          域值存儲表使用兩個文件表示:

          1. 域索引(.fdx文件)。
          如下,對于每個文檔這個文件包含指向域值的指針:
          FieldIndex (.fdx) --> <FieldValuesPosition>SegSize
          FieldValuesPosition --> Uint64
          FieldValuesPosition指示的是某一文檔的某域的域值在域值文件中的位置。因為域值文件

          含有定長的數據信息,因而很容易隨機訪問。在域值文件中,文檔n的域值信息就存在n*8

          位置處(The position of document n's field data is the Uint64 at n*8 in this

          file.)。

          2. 域值(.fdt文件)。
          如下,每個文檔的域值信息包含:
          FieldData (.fdt) --> <DocFieldData>SegSize
          DocFieldData --> FieldCount, <FieldNum, Bits, Value>FieldCount
          FieldCount --> VInt
          FieldNum --> VInt
          Bits --> Byte
          Value --> String
          目前情況下,Bits只有低位被使用,值為1表示域名被分解過,值為0表示未分解過。

          項字典(Term Dictionary)
          項字典用以下兩個文件表示:
          1. 項信息(.tis文件)。
          TermInfoFile (.tis)--> TermCount, TermInfos
          TermCount --> UInt32
          TermInfos --> <TermInfo>TermCount
          TermInfo --> <Term, DocFreq, FreqDelta, ProxDelta>
          Term --> <PrefixLength, Suffix, FieldNum>
          Suffix --> String
          PrefixLength, DocFreq, FreqDelta, ProxDelta
          --> VInt
          項信息按項排序。項信息排序時先按項所屬的域的文字順序排序,然后按照項的字串的文

          字順序排序。
          項的字前綴往往是共同的,與字的后綴組成字。PrefixLength變量就是表示與前一項相同

          的前綴的字數。因此,如果前一個項的字是"bone",后一個是"boy"的話,PrefixLength值

          為2,Suffix值為"y"。

          FieldNum指明了項屬于的域號,而域名存儲在.fdt文件中。
          DocFreg表示的是含有該項的文檔的數量。
          FreqDelta指明了項所屬TermFreq變量在.frq文件中的位置。詳細的說,就是指相對于前一

          個項的數據的位置偏移量(或者是0,表示文件中第一個項)。
          ProxDelta指明了項所屬的TermPosition變量在.prx文件中的位置。詳細的說,就是指相對

          于前一個項的數據的位置偏移量(或者是0,表示文件中第一個項)。

          2. 項信息索引(.tii文件)。
          每個項信息索引文件包含.tis文件中的128個條目,依照條目在.tis文件中的順序。這樣設

          計是為了一次將索引信息讀入內存能,然后使用它來隨機的訪問.tis文件。
          這個文件的結構和.tis文件非常類似,只在每個條目記錄上增加了一個變量IndexDelta。
          TermInfoIndex (.tii)--> IndexTermCount, TermIndices
          IndexTermCount --> UInt32
          TermIndices --> <TermInfo, IndexDelta>IndexTermCount
          IndexDelta --> VInt
          IndexDelta表示該項的TermInfo變量值在.tis文件中的位置。詳細的講,就是指相對于前

          一個條目的偏移量(或者是0,對于文件中第一個項)。

          項頻數(Frequencies)
          .frq文件包含每一項的文檔的列表,還有該項在對應文檔中出現的頻數。
          FreqFile (.frq) --> <TermFreqs>TermCount
          TermFreqs --> <TermFreq>DocFreq
          TermFreq --> DocDelta, Freq?
          DocDelta,Freq --> VInt
          TermFreqs序列按照項來排序(依據于.tis文件中的項,即項是隱含存在的)。
          TermFreq元組按照文檔號升序排列。
          DocDelta決定了文檔號和頻數。詳細的說,DocDelta/2表示相對于前一文檔號的偏移量(

          或者是0,表示這是TermFreqs里面的第一項)。當DocDelta是奇數時表示在該文檔中頻數

          為1,當DocDelta是偶數時,另一個VInt(Freq)就表示在該文檔中出現的頻數。
          例如,假設某一項在文檔7中出現一次,在文檔11中出現了3次,在TermFreqs中就存在如下

          的VInts序列: 15, 22, 3

          項位置(Position)
          .prx文件包含了某文檔中某項出現的位置信息的列表。
          ProxFile (.prx) --> <TermPositions>TermCount
          TermPositions --> <Positions>DocFreq
          Positions --> <PositionDelta>Freq
          PositionDelta --> VInt
          TermPositions按照項來排序(依據于.tis文件中的項,即項是隱含存在的)。
          Positions元組按照文檔號升序排列。
          PositionDelta是相對于前一個出現位置的偏移位置(或者為0,表示這是第一次在這個文

          檔中出現)。
          例如,假設某一項在某文檔第4項出現,在另一個文檔中第5項和第9項出現,將存在如下的

          VInt序列: 4, 5, 4

          標準化因子(Normalization Factor)
          .nrm文件包含了每個文檔的標準化因子,標準化因子用來以后乘以這個這個域的命中數。
          Norms (.nrm) --> <Byte>SegSize
          每個字節記錄一個浮點數。位0-2包含了3位的尾數部分,位3-8包含了5位的指數部分。
          按如下規則可將這些字節轉換為IEEE標準單精度浮點數:
          1. 如果該字節是0,就是浮點0;
          2. 否則,設置新浮點數的標志位為0;
          3. 將字節中的指數加上48后作為新的浮點數的指數;
          4. 將字節中的尾數映射到新浮點數尾數的高3位;并且
          5. 設置新浮點數尾數的低21位為0。

          被刪除的文檔(Deleted Document)
          .del文件是可選的,只有在某段中存在刪除操作后才存在:
          Deletions (.del) --> ByteCount,BitCount,Bits
          ByteSize,BitCount --> Uint32
          Bits --> <Byte>ByteCount
          ByteCount表示的是Bits列表中Byte的數量。典型的,它等于(SegSize/8)+1。
          BitCount表示Bits列表中多少個已經被設置過了。
          Bits列表包含了一些位(bit),順序表示一個文檔。當對應于文檔號的位被設置了,就標

          志著這個文檔已經被刪除了。位的順序是從低到高。因此,如果Bits包含兩個字節,0x00

          和0x02,那么表示文檔9已經刪除了。

          局限性(Limitations)
          在以上的文件格式中,好幾處都有限制項和文檔的最大個數為32位數的極限,即接近于40

          億。今天看來,這不會造成問題,但是,長遠的看,可能造成問題。因此,這些極限應該

          或者換為UInt64類型的值,或者更好的,換為VInt類型的值(VInt值沒有上限)。
          有兩處地方的代碼要求必須是定長的值,他們是:
          1. FieldValuesPosition變量(存儲于域索引文件中,.fdx文件)。它已經是一個UInt64

          型,所以不會有問題。
          2. TermCount變量(存儲于項信息文件中,.tis文件)。這是最后輸出到文件中的,但是

          最先被讀取,因此是存儲于文件的最前端 。索引代碼先在這里寫入一個0值,然后在其他

          文件輸出完畢后覆蓋這個值。所以無論它存儲在什么地方,它都必須是一個定長的值,它

          應該被變成UInt64型。
          除此之外,所有的UInt值都可以換成VInt型以去掉限制
          ------------------------------------------------------------------------------

          ---------
          下面是lucene組成結構中的類說明:
          org.apache.Lucene.search/ 搜索入口
          org.apache.Lucene.index/ 索引入口
          org.apache.Lucene.analysis/ 語言分析器
          org.apache.Lucene.queryParser/ 查詢分析器
          org.apache.Lucene.document/ 存儲結構
          org.apache.Lucene.store/? 底層IO/存儲結構
          org.apache.Lucene.util/ 一些公用的數據結構

          域存儲字段規則
          方法 切詞 索引 存儲 用途
          Field.Text(String name, String value) 切分詞索引并存儲,比如:標題,內容字段
          Field.Text(String name, Reader value)? 切分詞索引不存儲,比如:META信息,
          不用于返回顯示,但需要進行檢索內容
          Field.Keyword(String name, String value)? 不切分索引并存儲,比如:日期字段
          Field.UnIndexed(String name, String value)? 不索引,只存儲,比如:文件路徑
          Field.UnStored(String name, String value)? 只全文索引,不存儲

          建立索引的例子:
          public class IndexFiles {??
          //使用方法:: IndexFiles [索引輸出目錄] [索引的文件列表] ...??
          public static void main(String[] args) throws Exception {???
          String indexPath = args[0];??? IndexWriter writer;???
          //用指定的語言分析器構造一個新的寫索引器(第3個參數表示是否為追加索引)???

          writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false);???
          for (int i=1; i<args.length; i++) {?????
          System.out.println("Indexing file " + args[i]);?????
          InputStream is = new FileInputStream(args[i]);?????
          //構造包含2個字段Field的Document對象?????
          //一個是路徑path字段,不索引,只存儲?????
          //一個是內容body字段,進行全文索引,并存儲?????
          Document doc = new Document();?????
          doc.add(Field.UnIndexed("path", args[i]));?????
          doc.add(Field.Text("body", (Reader) new InputStreamReader(is)));?????
          //將文檔寫入索引????
          ?writer.addDocument(doc);?????
          is.close();??? };???
          //關閉寫索引器???
          writer.close();? }
          }
          索引過程中可以看到:

          語言分析器提供了抽象的接口,因此語言分析(Analyser)是可以定制的,雖然lucene缺省

          提供了2個比較通用的分析器SimpleAnalyser和StandardAnalyser,這2個分析器缺省都不

          支持中文,所以要加入對中文語言的切分規則,需要修改這2個分析器。
          Lucene并沒有規定數據源的格式,而只提供了一個通用的結構(Document對象)來接受索

          引的輸入,因此輸入的數據源可以是:數據庫,WORD文檔,PDF文檔,HTML文檔……只要能

          夠設計相應的解析轉換器將數據源構造成成Docuement對象即可進行索引。
          對于大批量的數據索引,還可以通過調整IndexerWrite的文件合并頻率屬性(mergeFactor

          )來提高批量索引的效率。
          檢索過程和結果顯示:

          搜索結果返回的是Hits對象,可以通過它再訪問Document==>Field中的內容。

          假設根據body字段進行全文檢索,可以將查詢結果的path字段和相應查詢的匹配度(score)

          打印出來,

          public class Search {??
          public static void main(String[] args) throws Exception {???
          String indexPath = args[0], queryString = args[1];???
          //指向索引目錄的搜索器???
          Searcher searcher = new IndexSearcher(indexPath);???
          //查詢解析器:使用和索引同樣的語言分析器???
          Query query = QueryParser.parse(queryString, "body",???????????????????????????

          ?? new SimpleAnalyzer());???
          //搜索結果使用Hits存儲???
          Hits hits = searcher.search(query);???
          //通過hits可以訪問到相應字段的數據和查詢的匹配度???
          for (int i=0; i<hits.length(); i++) {?????
          System.out.println(hits.doc(i).get("path") + "; Score: " +?????????????????????

          ??? hits.score(i));??? };? }
          }
          添加修改刪除指定記錄(Document)

          Lucene提供了索引的擴展機制,因此索引的動態擴展應該是沒有問題的,而指定記錄的修

          改也似乎只能通過記錄的刪除,然后重新加入實現。如何刪除指定的記錄呢?刪除的方法

          也很簡單,只是需要在索引時根據數據源中的記錄ID專門另建索引,然后利用

          IndexReader.delete(Termterm)方法通過這個記錄ID刪除相應的Document。

          根據某個字段值的排序功能
          根據某個字段值的排序功能

          lucene缺省是按照自己的相關度算法(score)進行結果排序的,但能夠根據其他字段進行

          結果排序是一個在LUCENE的開發郵件列表中經常提到的問題,很多原先基于數據庫應用都

          需要除了基于匹配度(score)以外的排序功能。而從全文檢索的原理我們可以了解到,任

          何不基于索引的搜索過程效率都會導致效率非常的低,如果基于其他字段的排序需要在搜

          索過程中訪問存儲字段,速度回大大降低,因此非常是不可取的。

          但這里也有一個折中的解決方法:在搜索過程中能夠影響排序結果的只有索引中已經存儲

          的docID和score這2個參數,所以,基于score以外的排序,其實可以通過將數據源預先排

          好序,然后根據docID進行排序來實現。這樣就避免了在LUCENE搜索結果外對結果再次進行

          排序和在搜索過程中訪問不在索引中的某個字段值。

          這里需要修改的是IndexSearcher中的HitCollector過程:

          ... scorer.score(new HitCollector() {?
          private float minScore = 0.0f;?
          public final void collect(int doc, float score) {??
          if (score > 0.0f &&???? // ignore zeroed buckets??????

          (bits==null || bits.get(doc))) {?? // skip docs not in bits????

          totalHits[0]++;???? if (score >= minScore) {????????????? /* 原先:Lucene將

          docID和相應的匹配度score例入結果命中列表中:??????? * hq.put(new ScoreDoc

          (doc, score));?? // update hit queue?????????????? * 如果用doc 或 1/doc 代替

          score,就實現了根據docID順排或逆排?????????????? * 假設數據源索引時已經按照某個

          字段排好了序,而結果根據docID排序也就實現了?????????????? * 針對某個字段的排序

          ,甚至可以實現更復雜的score和docID的擬合。?????????????? */?????????????

          hq.put(new ScoreDoc(doc, (float) 1/doc )); ??????
          if (hq.size() > nDocs) {??? // if hit queue overfull??

          hq.pop();???? // remove lowest in hit queue??

          minScore = ((ScoreDoc)hq.top()).score; // reset minScore?????? }???? }?

          ? }?}????? }, reader.maxDoc());

          Lucene面向全文檢索的優化在于首次索引檢索后,并不把所有的記錄(Document)具體內

          容讀取出來,而起只將所有結果中匹配度最高的頭100條結果(TopDocs)的ID放到結果集

          緩存中并返回,這里可以比較一下數據庫檢索:如果是一個10,000條的數據庫檢索結果集

          ,數據庫是一定要把所有記錄內容都取得以后再開始返回給應用結果集的。所以即使檢索

          匹配總數很多,Lucene的結果集占用的內存空間也不會很多。對于一般的模糊檢索應用是

          用不到這么多的結果的,頭100條已經可以滿足90%以上的檢索需求。

          如果首批緩存結果數用完后還要讀取更后面的結果時Searcher會再次檢索并生成一個上次

          的搜索緩存數大1倍的緩存,并再重新向后抓取。所以如果構造一個Searcher去查1-120條

          結果,Searcher其實是進行了2次搜索過程:頭100條取完后,緩存結果用完,Searcher重

          新檢索再構造一個200條的結果緩存,依此類推,400條緩存,800條緩存。由于每次

          Searcher對象消失后,這些緩存也訪問那不到了,你有可能想將結果記錄緩存下來,緩存

          數盡量保證在100以下以充分利用首次的結果緩存,不讓Lucene浪費多次檢索,而且可以分

          級進行結果緩存。

          Lucene的另外一個特點是在收集結果的過程中將匹配度低的結果自動過濾掉了。這也是和

          數據庫應用需要將搜索的結果全部返回不同之處。

          posted @ 2006-11-08 14:58 Lansing 閱讀(1365) | 評論 (0)編輯 收藏

          Eclipse及其插件介紹和下載- -

          TagEclipse ?? 插件 ?? ??????????????????????????????????????

          0.Eclipse下載
          EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在這里下載
          http://www.eclipse.org/downloads/index.php
          ?
          0.5.lomboz J2EE插件,開發JSP,EJB
          http://forge.objectweb.org/projects/lomboz
          1.MyEclipse J2EE開發插件,支持SERVLET/JSP/EJB/數據庫操縱等
          http://www.myeclipseide.com
          ?
          2.Properties Editor? 編輯java的屬性文件,并可以自動存盤為Unicode格式
          http://propedit.sourceforge.jp/index_en.html
          ?
          3.Colorer Take? 為上百種類型的文件按語法著色
          http://colorer.sourceforge.net/
          ?
          4.XMLBuddy 編輯xml文件
          http://www.xmlbuddy.com
          ?
          5.Code Folding? 加入多種代碼折疊功能(比eclipse自帶的更多)
          http://www.coffee-bytes.com/servlet/PlatformSupport
          ?
          6.Easy Explorer? 從eclipse中訪問選定文件、目錄所在的文件夾
          http://easystruts.sourceforge.net/
          ?
          7.Fat Jar 打包插件,可以方便的完成各種打包任務,可以包含外部的包等
          http://fjep.sourceforge.net/
          ?
          8.RegEx Test 測試正則表達式
          http://brosinski.com/stephan/archives/000028.php
          ?
          9.JasperAssistant 報表插件(強,要錢的)
          http://www.jasperassistant.com/
          ?
          10.Jigloo GUI Builder JAVA的GUI編輯插件
          http://cloudgarden.com/jigloo/
          ?
          11.Profiler 性能跟蹤、測量工具,能跟蹤、測量BS程序
          http://sourceforge.net/projects/eclipsecolorer/
          ?
          12.AdvanQas 提供對if/else等條件語句的提示和快捷幫助(自動更改結構等)
          http://eclipsecolorer.sourceforge.net/advanqas/index.html
          ?
          13.Log4E Log4j插件,提供各種和Log4j相關的任務,如為方法、類添加一個logger等
          http://log4e.jayefem.de/index.php/Main_Page
          ?
          14.VSSPlugin VSS插件
          http://sourceforge.net/projects/vssplugin
          ?
          15.Implementors 提供跳轉到一個方法的實現類,而不是接中的功能(實用!)
          http://eclipse-tools.sourceforge.net/implementors/
          ?
          16.Call Hierarchy 顯示一個方法的調用層次(被哪些方法調,調了哪些方法)
          http://eclipse-tools.sourceforge.net/call-hierarchy/index.html
          ?
          17.EclipseTidy 檢查和格式化HTML/XML文件
          http://eclipsetidy.sourceforge.net/
          ?
          18.Checkclipse 檢查代碼的風格、寫法是否符合規范
          http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm
          ?
          19.Hibernate Synchronizer Hibernate插件,自動映射等
          http://www.binamics.com/hibernatesync/
          ?
          20.VeloEclipse? Velocity插件
          http://propsorter.sourceforge.net/
          ?
          21.EditorList 方便的列出所有打開的Editor
          http://editorlist.sourceforge.net/
          ?
          22.MemoryManager 內存占用率的監視
          http://cloudgarden.com/memorymanager/
          ?
          23.swt-designer java的GUI插件
          http://www.swt-designer.com/
          ?
          24.TomcatPlugin 支持Tomcat插件
          http://www.sysdeo.com/eclipse/tomcatPlugin.html
          ?
          25.XML Viewer
          http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html
          ?
          26.quantum 數據庫插件
          http://quantum.sourceforge.net/
          ?
          27.Dbedit 數據庫插件
          http://sourceforge.net/projects/dbedit
          ?
          28.clay.core 可視化的數據庫插件
          http://www.azzurri.jp/en/software/index.jsp
          http://www.azzurri.jp/eclipse/plugins
          ?
          29.hiberclipse hibernate插件
          http://hiberclipse.sourceforge.net
          http://www.binamics.com/hibernatesync
          ?
          30.struts-console Struts插件
          http://www.jamesholmes.com/struts/console/
          ?
          31.easystruts Struts插件
          http://easystruts.sourceforge.net
          ?
          32.veloedit Velocity插件
          http://veloedit.sourceforge.net/
          ?
          33.jalopy 代碼整理插件
          http://jalopy.sourceforge.net/
          ?
          34.JDepend 包關系分析
          http://andrei.gmxhome.de/jdepend4eclipse/links.html
          ?
          35.Spring IDE Spring插件
          http://springide-eclip.sourceforge.net/updatesite/
          ?
          36.doclipse 可以產生xdoclet 的代碼提示
          http://beust.com/doclipse/

          posted @ 2006-09-21 19:17 Lansing 閱讀(314) | 評論 (0)編輯 收藏

          Struts常見異常信息和解決方法

          以下所說的struts-config.xml和ApplicationResources.properties等文件名是缺省時使用的,如果你使用了多模塊,或指定了不同的資源文件名稱,這些名字要做相應的修改。

          1、“No bean found under attribute key XXX”
          在struts-config.xml里定義了一個ActionForm,但type屬性指定的類不存在,type屬性的值應該是Form類的全名。或者是,在Action的定義中,name或attribute屬性指定的ActionForm不存在。

          2、“Cannot find bean?XXX in any scope”
          在Action里一般會request.setAttribute()一些對象,然后在轉向的jsp文件里(用tag或request.getAttribute()方法)得到這些對象并顯示出來。這個異常是說jsp要得到一個對象,但前面的Action里并沒有將對象設置到request(也可以是session、servletContext)里。
          可能是名字錯了,請檢查jsp里的tag的一般是name屬性,或getAttribute()方法的參數值;或者是Action邏輯有問題沒有執行setAttribute()方法就先轉向了。
          還有另外一個可能,純粹是jsp文件的問題,例如<logic:iterate>會指定一個id值,然后在循環里<bean:write>使用這個值作為name的值,如果這兩個值不同,也會出現此異常。(都是一個道理,request里沒有對應的對象。)

          3、“Missing message for key "XXX"”
          缺少所需的資源,檢查ApplicationResources.properties文件里是否有jsp文件里需要的資源,例如:

          < bean:message?key = " msg.name.prompt " />

          這行代碼會找msg.name.prompt資源,如果AppliationResources.properties里沒有這個資源就會出現本異常。在使用多模塊時,要注意在模塊的struts-config-xxx.xml里指定要使用的資源文件名稱,否則當然什么資源也找不到,這也是一個很容易犯的錯誤。

          4、“No getter method for property?XXX of bean teacher”
          這條異常信息說得很明白,jsp里要取一個bean的屬性出來,但這個bean并沒有這個屬性。你應該檢查jsp中某個標簽的property屬性的值。例如下面代碼中的cade應該改為code才對:

          < bean:write?name = " teacher " ?property = " cade " ?filter = " true " />

          5、“Cannot find ActionMappings or ActionFormBeans collection”
          待解決。

          6、“Cannot retrieve mapping for action XXX”
          在.jsp的<form>標簽里指定action='/XXX',但這個Action并未在struts-config.xml里設置過。

          7、HTTP Status 404 - /xxx/xxx.jsp
          Forward的path屬性指向的jsp頁面不存在,請檢查路徑和模塊,對于同一模塊中的Action轉向,path中不應包含模塊名;模塊間轉向,記住使用contextRelative="true"。

          8、沒有任何異常信息,顯示空白頁面
          可能是Action里使用的forward與struts-config.xml里定義的forward名稱不匹配。

          9、“The element type "XXX" must be terminated by the matching end-tag "XXX".”
          這個是struts-config.xml文件的格式錯誤,仔細檢查它是否是良構的xml文件,關于xml文件的格式這里就不贅述了。

          10、“Servlet.init() for servlet action threw exception”
          一般出現這種異常在后面會顯示一個關于ActionServlet的異常堆棧信息,其中指出了異常具體出現在代碼的哪一行。我曾經遇到的一次提示如下:

          java.lang.NullPointerException
          ????at?org.apache.struts.action.ActionServlet.parseModuleConfigFile(ActionServlet.java:
          1003 )
          ????at?org.apache.struts.action.ActionServlet.initModuleConfig(ActionServlet.java:
          955 )


          為解決問題,先下載struts的源碼包,然后在ActionServlet.java的第1003行插入斷點,并對各變量進行監視。很丟人,我竟然把struts-config.xml文件弄丟了,因此出現了上面的異常,應該是和CVS同步時不小心刪除的。

          11、“Resources not defined for Validator”
          這個是利用Validator插件做驗證時可能出現的異常,這時你要檢查validation.xml文件,看里面使用的資源是否確實有定義,form的名稱是否正確,等等。

          posted @ 2006-09-19 11:34 Lansing 閱讀(336) | 評論 (0)編輯 收藏
               摘要: PowerDesigner 設計數據庫 ? ? ? ?????? 本文檔不講述如何使用 PowerDesigner ,而是講述如何將 PowerDesigner...  閱讀全文
          posted @ 2006-09-13 14:53 Lansing 閱讀(677) | 評論 (0)編輯 收藏
          Log4j由三個重要的組件構成:日志信息的優先級,日志信息的輸出目的地,日志信息的輸出格式。日志信息的優先級從高到低有ERROR、WARN、INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制臺還是文件中;而輸出格式則控制了日志信息的顯示內容。

            一、定義配置文件

            其實您也可以完全不使用配置文件,而是在代碼中配置Log4j環境。但是,使用配置文件將使您的應用程序更加靈活。Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件(鍵=值)。下面我們介紹使用Java特性文件做為配置文件的方法:

            1.配置根Logger,其語法為:

            log4j.rootLogger = [ level ] , appenderName, appenderName, …

            其中,level 是日志記錄的優先級,分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級別。Log4j建議只使用四個級別,優先級從高到低分別是ERROR、WARN、INFO、DEBUG。通過在這里定義的級別,您可以控制到應用程序中相應級別的日志信息的開關。比如在這里定義了INFO級別,則應用程序中所有DEBUG級別的日志信息將不被打印出來。 appenderName就是指定日志信息輸出到哪個地方。您可以同時指定多個輸出目的地。

            2.配置日志信息輸出目的地Appender,其語法為:

            log4j.appender.appenderName = fully.qualified.name.of.appender.class
            log4j.appender.appenderName.option1 = value1
            …
            log4j.appender.appenderName.option = valueN

            其中,Log4j提供的appender有以下幾種:
            org.apache.log4j.ConsoleAppender(控制臺),
            org.apache.log4j.FileAppender(文件),
            org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件),
            org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件),
            org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)

            3.配置日志信息的格式(布局),其語法為:

            log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
            log4j.appender.appenderName.layout.option1 = value1
            …
            log4j.appender.appenderName.layout.option = valueN

            其中,Log4j提供的layout有以下幾種:
            org.apache.log4j.HTMLLayout(以HTML表格形式布局),
            org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
            org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
            org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等等信息)

            Log4J采用類似C語言中的printf函數的打印格式格式化日志信息,打印參數如下: %m 輸出代碼中指定的消息

            %p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL
            %r 輸出自應用啟動到輸出該log信息耗費的毫秒數
            %c 輸出所屬的類目,通常就是所在類的全名
            %t 輸出產生該日志事件的線程名
            %n 輸出一個回車換行符,Windows平臺為“\r\n”,Unix平臺為“\n”
            %d 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
            %l 輸出日志事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數。舉例:Testlog4.main(TestLog4.java:10)

            二、在代碼中使用Log4j

            1.得到記錄器

            使用Log4j,第一步就是獲取日志記錄器,這個記錄器將負責控制日志信息。其語法為:

            public static Logger getLogger( String name)

            通過指定的名字獲得記錄器,如果必要的話,則為這個名字創建一個新的記錄器。Name一般取本類的名字,比如:

            static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

            2.讀取配置文件

            當獲得了日志記錄器之后,第二步將配置Log4j環境,其語法為:

            BasicConfigurator.configure (): 自動快速地使用缺省Log4j環境。
            PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。
            DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。

            3.插入記錄信息(格式化日志信息)

            當上兩個必要步驟執行完畢,您就可以輕松地使用不同優先級別的日志記錄語句插入到您想記錄日志的任何地方,其語法如下:

            Logger.debug ( Object message ) ;
            Logger.info ( Object message ) ;
            Logger.warn ( Object message ) ;
            Logger.error ( Object message ) ;

          posted @ 2006-08-22 14:28 Lansing 閱讀(361) | 評論 (0)編輯 收藏
          速度瓶頸問題的提出

            在企業級的Java應用中,訪問數據庫是一個必備的環節。數據庫作為數據資源的集散地,往往位于企業級軟件體系的后方,供前方的應用程序訪問。在Java技術的體系中,應用程序是通過JDBC(Java Database Connectivity)接口來訪問數據庫的,JDBC支持"建立連接、SQL語句查詢、處理結果"等基本功能。在應用JDBC接口訪問數據庫的過程中,只要根據規范來操作,這些功能的實現不會出差錯。但是,有些時候進行數據查詢的效率著實讓開發人員懊惱不已,明明根據規范編寫的程序,卻得不到預期的運行效果,造成了整個軟件的執行效率不高。

            起初,我們把問題歸結于Java字節碼加載和執行速度的緩慢,緊接著硬件的功能普遍得到了增強,證明這樣的想法些許是錯誤的,還沒有抓到真正的根本原因。本文將逐步解剖JDBC訪問數據庫的機制,深層分析造成這種速度瓶頸問題的原因,并提出在現有的Java技術框架下解決這個速度瓶頸問題的思路和方法。

            JDBC訪問數據庫的機制

          ????????????????
          圖1????????????????????????????????????????????????圖2

            圖1和圖2描述了Java應用程序通過JDBC接口訪問數據庫的4種驅動模式,也就是底層實現JDBC接口的模式。對于這些模式,我們逐一介紹:

            模式4:圖1左邊的分支稱為模式4,它一般是數據庫廠商才能實現的純Java的基于本地協議的驅動,直接調用DBMS(數據庫管理系統)使用的網絡協議,對于企業內部互聯網來說,是一個實用的解決方案。

            模式3:圖1右邊的分支稱為模式3,它同樣是一個純Java驅動,不同于模式4的是基于網絡協議。它的機制是將JDBC調用轉換為中間網絡協議,然后轉換為DBMS協議。中間網絡協議層起到一個讀取數據庫的中間件的作用,能夠連接許多類型的數據庫,因而是最靈活的JDBC模式。這種模式的產品比較適用于企業內部互聯網,如若支持國際互聯網,還需添加對安全、穿過防火墻訪問等的支持。

            模式1:圖2左邊的分支稱為模式1,即通常由Sun公司提供的JDBC-ODBC橋接器。它提供了經由一種或多種ODBC驅動進行訪問的JDBC接口,而ODBC驅動,在很多情況下也即數據庫的客戶端,必須加載到客戶機。因而,它適用于下載和自動安裝Java程序不重要、實驗用途或者沒有其它JDBC驅動可用的情況下。

            模式2:圖2右邊的分支成為模式2,類似于JDBC-ODBC橋接器,需要加載到客戶機,卻是一個部分用Java實現的驅動接口。它將JDBC調用轉換為對數據庫(Oracle、Sybase、Informix、DB2等)客戶端接口的調用。

            不同模式的JDBC接口的選擇

            以上闡述的JDBC接口的模式不同,讓我們可以把JDBC接口按照實現的模式分為四類。有些同仁可能有這樣的體會,選擇不同的JDBC接口會有不同的訪問速度,為何會出現這樣的情況?這個問題的答案是,不同的應用需要不同模式的JDBC接口,因而我們在面對一個應用時,要慎重選擇JDBC接口。

            通常的DBMS都支持微軟提出的ODBC規范,因而模式1可當作您在設計和實現軟件時的選擇,它易于配置的特性能夠讓你把選擇JDBC等煩惱的問題暫且拋在一邊,讓自己的Java程序能夠及早地正常工作起來。

            一般說來,商業DBMS的提供者往往會為自己的數據庫提供一個JDBC接口,應用的是模式4。這種模式的優勢在于和數據庫本身結合比較緊密,而且是純Java的實現,在企業級的軟件應用中,應該是首選。例如,對于Oracle數據庫來說,有Oracle、SilverStream、DataDirect等公司提供這種類型的驅動,其性能往往被評價為最高效的、最可靠的驅動程序。但偶爾也有比較麻煩的情況,例如微軟就不會提供MS SQL的JDBC接口,這時就需要到Sun的網站(http://industry.java.sun.com/products/jdbc/drivers)查找相關的模式4驅動,上面提到的DataDirect公司(http://www.datadirect-technologies.com/jdbc/jdbc.asp)就提供了支持MS SQL的模式4驅動,只是你需要支付750$購買這個JDBC驅動。

            同樣是純Java實現的模式3,與模式4相比,優勢在于對多種數據庫的支持,體現了其靈活性。在大型的企業級的軟件應用中,后臺數據庫往往不是一個,而且是由不同的廠商支持的。不過,模式3的JDBC驅動往往提供許多企業級的特征,例如SSL安全、支持分布式事務處理和集中管理等,因而會對你特殊的用途有很大的幫助。是否選用,還在于你對擴展應用是否有需求以及對多DBMS的支持。

            談到這兒,我對模式3和模式4作一個總結:兩者都是純Java實現的驅動,因而不需要數據庫廠商提供附加的軟件,就可以運行在任何標準的Java平臺,性能上比較高效、可靠。

            了解上述3種JDBC的實現模式之后,模式2就更容易闡釋了,你可以理解它為前三者利弊平衡的妥協產物:

            1. 借鑒模式1利用客戶機本地代碼庫,加速數據訪問的執行,但卻摒除ODBC標準,而是支持廠商自己指定的性能擴展
            2. 借鑒模式3利用多層結構,上層用Java實現,利于跨平臺應用和支持多數據庫,但下層卻改為本地代碼,加速執行速度
            3. 借鑒模式4和數據庫結合緊密的優點,部分用Java實現,更是對數據庫性能有很大的擴展

            這種開放和高性能的特征得到了業界的肯定,因而被主要的數據庫廠商強烈推薦。盡管它需要你下載本地代碼庫到客戶機,但相對于你訪問數據庫速度的提高,這些應該只是舉手之勞了。下面對4種實現JDBC的模式選擇,歸納一下選擇的順序(當然是指你有選擇余地的時候,不存在的話向后推延):

          編號 選擇過程分析 選擇順序
          1 實驗性環境下,盡可能選擇易于配置的驅動,利于Java程序的開發,后期可在對應用環境進行判斷后,再對JDBC模式進行選擇 1>2>3>4
          2 小型企業級環境下,不需要對多數據庫的支持,因而模式2和3的有些優點并不能體現出來,強烈推薦你選擇模式4的JDBC驅動 4>2=3>1
          3 大型企業級環境下,需要對多數據庫的支持,模式2和3各有千秋,但是更多情況下是你會選擇速度較快的模式2 2>3>4>1

            對于不同廠商提供的但應用相同模式的JDBC接口,理論上比較不出效率的高低,你只有通過一定的工具,例如Benchmark等,對它們進行比較才能更有利于你的選擇。因為暫時不存在第三方提供的數據比較結果,所以這些問題需要你對上述內容有了透徹理解之后自行解決。

            Java程序中SQL語句格式的優化

            這個時候,你也許還在為找不到合適的JDBC驅動而一籌莫展,也許為自己在凌晨3點下載的JDBC驅動通過了測試而欣喜若狂,但是并不說明你對程序的優化工作已經無關緊要了。切記,對整個軟件系統的優化,包括每個環節的優化,要不有可能你會前功盡棄。我在這兒不和大家討論Java程序的算法,而是簡單闡述一下選擇SQL語句格式的必要和如何選擇對自己有利的SQL語句格式??聪旅鎯啥纬绦蚱瑪啵?/p>

            Code Fragment 1:

            String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE 'Colombian'";
            stmt.executeUpdate(updateString);

            Code Fragment 2:

            PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
            updateSales.setInt(1, 75);
            updateSales.setString(2, "Colombian");
            updateSales.executeUpdate();

            片斷2和片斷1的區別在于,后者使用了PreparedStatement對象,而前者是普通的Statement對象。PreparedStatement對象不僅包含了SQL語句,而且大多數情況下這個語句已經被預編譯過,因而當其執行時,只需DBMS運行SQL語句,而不必先編譯。當你需要執行Statement對象多次的時候,用PreparedStatement對象將會大大降低運行時間,當然也加快了訪問數據庫的速度。

            這種轉換也給你帶來很大的便利,不必重復SQL語句的句法,而只需更改其中變量的值,便可重新執行SQL語句。選擇PreparedStatement對象與否,在于相同句法的SQL語句是否執行了多次,而且兩次之間的差別僅僅是變量的不同。如果僅僅執行了一次的話,它應該和普通的Statement對象毫無差異,體現不出它預編譯的優越性。

            軟件模型中對數據庫訪問的設計模式的優化

            在我閱讀J2EE藍圖和JDO草案的過程中,我發現了訪問模式對數據庫訪問的影響,因而想在本文中闡述如何針對自己的軟件需求選擇合適的軟件模式。

            J2EE藍圖的設計者在Java Pet Store示例應用中使用了MVC(Model-View-Controller)體系,給許多J2EE設計模式提供了背景。我要談及的三種設計模式是:Data Access Object、Fast Lane Reader、Page-by-Page Iterator,它們為加快數據存取速度提供了一些可以在系統設計階段值得我們借鑒的想法。

            Data Access Object

            將商業邏輯從數據存取邏輯中分離出來,把存取的資源改編,從而使資源可以容易和獨立地轉變。

            依賴于底層數據資源的特殊要素(例如數據庫的供應商)的商業組件,常將商業邏輯和數據存取邏輯配合起來,只能使用特殊類型的資源,而使用不同類型的資源時,復用將會非常困難,因此,只能服務于有限的市場領域。DAO(Data Access Object)即是將數據存取邏輯從EJB中抽去出來抽象為一個獨立的接口,EJB根據接口的操作執行商業邏輯,而接口針對使用的數據資源實現為DAO對象。

            在Java Pet Shop這個例子中,OrderEJB組件通過關聯的OrderDAO類訪問數據庫,自身則關注于商業邏輯的實現。在調度階段,將配置某一類(OrderDAOCS、OrderDAOOracle或OrderDAOSybase)為OrderDAO的實現,而OrderEJB無須任何更改。圖3更能幫助你明白其中的道理:


          圖3 Data Access Object的設計模式

            此舉增加了數據存取的彈性、資源的獨立性和擴展性,但復雜度有相應的提高,其它附帶的問題我們不在這兒討論。

            Fast Lane Reader

            拋棄EJB,加速只讀數據的存取。

            有些時候,高效地存取數據比獲得最新的數據更重要。在Java Pet Store中,當一個用戶瀏覽商店的目錄時,屏幕與數據庫內容吻合不是至關緊要的,相反,迅速顯示和重新獲得非常重要。FLR模式可以加速從資源中重新獲得大型的列數據項的速度,它不用EJB,而是更直接地通過DAO來存取數據,從而消除EJB的經常開支(例如遠程方法調用、事務管理和數據序列化等)。

            在Java Pet Store這個例子中,當一個用戶瀏覽目錄時,通過CatalogDAO(而不是CatalogEJB)從數據庫加載數據項,而CatalogDAO是一個Fast Lane Reader的實例,使得讀訪問變得迅速,如圖4:


          圖4 Fast Lane Reader設計模式

            與DAO模式不同的是,FLR是一個優化的模式,但不是要替代原有的訪問機制,而是作為補充使其完備。當你頻繁地只讀大型的列數據和不必存取最新的數據時,使用FLR將是非常合適的。

            Page-by-Page Iterator

            為了高效地存取大型的遠程數據列,一下子通過重新獲得其元素為一個子列的Value Object(提高遠程傳輸效率的設計模式,這兒不詳盡描述)。

            分布式數據庫的應用經常需要用戶考慮一長列數據項,例如一個目錄或一個搜索結果的集合。在這些情況下,立刻提供全列的數據經常不必要(用戶并不是對所有的數據項感興趣)或不可能(沒有足夠的空間)。此外,當重新獲得一列數據項時,使用Entity Bean的代價將非常高昂,一個開銷來自于使用遠程探測器來收集Requested Bean,另外,更大的開銷來自對每個Bean產生遠程調用以從用戶獲得數據。

            通過Iterator,客戶機對象能一下子重新獲得一個子列或者頁的Value Object,每一頁都剛好滿足客戶機的需求,因此,程序使用較少的資源滿足了客戶機的立刻需求。

            在Java Pet Store這個例子中,JSP頁面product.jsp任何時候只顯示一個數據列的一部分,從ProductItemListTag(Page-by-Page Iterator)重新獲得數據項,當客戶機希望看到列中的別的數據項,product.jsp再次調用Iterator重新獲得這些數據項,流程見圖5:


          圖5 Page-by-Page Iterator設計模式

            以上設計模式的應用向我們表明,在某些特殊情況下,優化對數據庫的訪問模型,既可滿足用戶的需求又可提高訪問數據庫的效率。這給我們一個思路,就是:在你的硬件環境可能會產生瓶頸的情況下,可以通過對軟件模型的優化來達到滿足需求的目的。上述三種設計模式的應用情形為:

          Data Access Object 需要將商業邏輯和數據存取邏輯分離;
          在調度的時刻,需要支持選擇數據源的類型;
          使用的數據源的類型的變化,對商業對象或其它客戶端完成數據存取沒有影響。
          Fast Lane Reader 面對大型的列數據,需要經常的只讀訪問;
          訪問最新的數據并不是至關緊要的事情。
          Page-by-Page Iterator 存取大型的服務器端數據列;
          任何時刻,用戶只對列的一部分內容感興趣;
          整個列的數據不適合在客戶端顯示;
          整個列的數據不適合在存儲器中保存;
          傳輸整個列的數據將耗費太多的時間。

            在顯示商品目錄的時候,我們選擇了DAO和FLR的結合,因為它們兩者的條件都得到了滿足(需要分離商業邏輯和數據存取邏輯,經常的只讀訪問和對即時性不敏感),此時應用將會大大發揮它們的優點。而在進行內容檢索的時候,我們會選擇PPI,因為也許檢索出了上千條的記錄,但是用戶沒有興趣立即閱讀全部內容,而是一次十條地閱讀,或者他在閱讀完前十條記錄后發覺自己的目的已經達到,接下來瀏覽別的網頁了,都不必我們一次性地傳輸上千條記錄給他,所以也是PPI的應用條件得到了滿足,結果則是此模式的優點得到了發揮,又不影響全局的數據訪問。

            在進行軟件模型的設計時,整體的框架可以應用某些優秀的、通用的設計模式,這樣既加快模型的建立速度,又能和其它系統集成。但是,碰到一些瓶頸問題的情況下,我們就需要對局部的設計模式做一些調整,以優化整個系統,上述三個模式就是對原有體系的補充,它們并沒有對整體的框架做出巨大的改變,卻突破了某些瓶頸(瓶頸往往是局部的)障礙,讓我們的產品更好地服務于用戶。

            將深入研究的問題

            開篇至今,我們主要探討了軟件層次上的解決問題,但是,必須肯定一點,如果你的硬件環境非常差(運行Java都有困難)或非常好(額外的存儲空間、超快的運算速度和富裕的網絡帶寬),上述途徑對你來說很難有大的幫助。前一種情況,我建議你升級硬件設備到軟件廠商推薦的配置(強烈反對最小配置),以使應用服務器、數據庫、Java等軟件能夠運行自如;后一種情況,我沒什么話可說,花錢是解決這個問題最好的辦法。

            本文并未談及線程池和告訴緩沖這兩個非常重要的概念,因為筆者認為,它們是針對局部時間高訪問量的瓶頸問題的解決,不能理解為簡單的速度瓶頸問題,所以我會在下一篇文章中分析這種特殊的情況和提出解決問題的辦法。也許你對這一點更關心一些,認為自己的問題就出在這個地方,這是非常好的思考問題的方式,你已經抓住了問題的關鍵。但是,我還是建議你通讀一下本文,讓自己對速度瓶頸問題有更好的理解,并掌握在解決問題的過程中,分辨常態和暫態,從而選擇不同的思路入手。其實,本文談及的就是速度瓶頸問題的常態,而下一篇文章討論的將會是暫態,希望你能夠漸入佳境。

            JDO(Java Data Object)是需要我們關注的一個API,它定義了新的數據存取模型,直接借鑒了DAO設計模式。不同的數據源,有不同的數據存取技術,就有不同的API供開發人員使用。JDO正是為了解決這個問題而產生的,它實現了即插即用的數據存取的實現和持久信息(包括企業數據和本地存儲的數據)以Java為中心的視圖。因此,開發人員只關注創建那些實現商業邏輯的類和用它們來表現數據源的數據,而這些類和數據源之間的映射則由那些EIS領域的專家來完成。如果大家對JDO感興趣的話,那么我會寫第三篇文章把其詳細介紹給大家,并給出示例應用。

          posted @ 2006-08-22 09:32 Lansing 閱讀(441) | 評論 (0)編輯 收藏
          批量處理JDBC語句提高處理速度

          作者:佚名????來自:未知

            有時候JDBC運行得不夠快,這使得有些程序員使用數據庫相關的存儲過程。作為一個替代方案,可以試試使用Statement 的批量處理特性看看能否同時執行所有的SQL以提高速度。

            存儲過程的最簡單的形式就是包含一系列SQL語句的過程,將這些語句放在一起便于在同一個地方管理也可以提高速度。Statement 類可以包含一系列SQL語句,因此允許在同一個數據庫事務執行所有的那些語句而不是執行對數據庫的一系列調用。

            使用批量處理功能涉及下面的兩個方法:
            · addBatch(String) 方法
            · executeBatch方法

            如果你正在使用Statement 那么addBatch 方法可以接受一個通常的SQL語句,或者如果你在使用PreparedStatement ,那么也可以什么都不向它增加。executeBatch 方法執行那些SQL語句并返回一個int值的數組,這個數組包含每個語句影響的數據的行數。如果將一個SELECT語句或者其他返回一個ResultSet的SQL語句放入批量處理中就會導致一個SQLException異常。

            關于java.sql.Statement 的簡單范例可以是:

            Statement stmt = conn.createStatement();
            stmt.insert("DELETE FROM Users");
            stmt.insert("INSERT INTO Users VALUES("rod", 37, "circle")");
            stmt.insert("INSERT INTO Users VALUES("jane", 33, "triangle")");
            stmt.insert("INSERT INTO Users VALUES("freddy", 29, "square")");
            int[] counts = stmt.executeBatch();

            PreparedStatement 有些不同,它只能處理一部分SQL語法,但是可以有很多參數,因此重寫上面的范例的一部分就可以得到下面的結果:

            // 注意這里沒有DELETE語句
            PreparedStatement stmt = conn.prepareStatement("INSERT INTO Users VALUES(?,?,?)");

            User[ ] users = ...;
            for(int i=0; i<users.length; i++) {
             stmt.setInt(1, users[i].getName());
             stmt.setInt(2, users[i].getAge());
             stmt.setInt(3, users[i].getShape());
             stmt.addBatch( );
            }
            int[ ] counts = stmt.executeBatch();

            如果你不知道你的語句要運行多少次,那么這是一個很好的處理SQL代碼的方法。在不使用批量處理的情況下,如果添加50個用戶,那么性能就有影響,如果某個人寫了一個腳本添加一萬個用戶,程序可能變得很糟糕。添加批處理功能就可以幫助提高性能,而且在后面的那種情況下代碼的可讀性也更好。

          posted @ 2006-08-22 09:24 Lansing 閱讀(428) | 評論 (0)編輯 收藏
          <2006年8月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          歡迎探討,努力學習Java哈

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          Lansing's Download

          Lansing's Link

          我的博客

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 安西县| 温宿县| 靖江市| 财经| 嘉祥县| 武胜县| 崇阳县| 洛宁县| 江永县| 英山县| 兴业县| 屏南县| 政和县| 清苑县| 大邑县| 广丰县| 河曲县| 合江县| 逊克县| 尼玛县| 兴国县| 科尔| 武平县| 丹寨县| 岐山县| 天峻县| 嘉荫县| 德阳市| 阿拉善盟| 新巴尔虎右旗| 古浪县| 石嘴山市| 务川| 民丰县| 玉树县| 望城县| 商河县| 福海县| 泸西县| 原阳县| 南皮县|