csusky

          常用鏈接

          統計

          最新評論

          #

          數據庫的事務 JDBC

          TRANSACTION_NONE:
            正式地講,TRANSACTION_NONE不是一個有效的事務級別。
            根據java.sql Connection API文件,這個級別表示事務是
            不被支持的,因此理論上說你不能使用TRANSACTION_NONE作
            為一個自變量賦給Connection.setTransactionIsolation()
            方法。事實上,雖然一些數據庫實施了這個事務級別,但是
            Oracle9i卻沒有實施。


           臟讀取(TRANSACTION_READ_UNCOMMITTE):
          (允許的操作       讀-讀  讀-寫 寫-讀     (臟數據,不可重復讀,虛讀) )
             表示,這個事務級別
            允許讀取臟數據,什么是臟數據?就是指還沒有提交的數據.
            因為這個級別,是允許一個事務(A)讀取另一個事務(B)
            還沒有提交的數據.一旦事務B發生異常退出.而修改了的數據
            卻還沒提交,或者新插入的數據和刪除了的數據都還沒有
            提交,導致事務A拿到了一些臟數據,或者錯誤數據;
            因此在這個事務級別里是會發生臟讀,重復讀,錯誤讀取;

           禁止臟讀(TRANSACTION_READ_COMMITTED):
          (允許的操作       讀-讀  讀-寫 (不可重復讀,虛讀))
            在這個級別中,事務A
            只能讀取一些提交的數據,如事務B添加了一條記錄,但是
            如果事務B沒有提交,那么事務A是讀不到的,所以該事務級別,
            把臟讀給屏蔽掉了.---卻允許重復讀取,和錯誤讀取.

            什么是重復讀取呢?譬如,事務A讀取了一個數據,這個數據
            的值為"helloworld",事務A準備利用這個數據來更新一下
            其他數據,但這個時候事務B開始對這個數據進行修改,并且
            提交---"hello 無名氏",由于是已經提交了,所以事務A是可以
            看到這個數據的,當事務A在沒提交事務之前,它想看下數據
            是否正確,這個時候它發現,新讀出的數據已經和原來的數據
            不一樣了(這就是重復讀取);




           允許重復讀取(TRANSACTION_REPEATABLE_READ):
          (允許的操作       讀-讀  讀-寫(僅允許插入,不允許刪除和修改)(虛讀))
            在這個級別中,
            是禁止了臟讀,和取消了不可重復讀取,但是沒有禁止錯誤讀取;
            這個級別的事務比較嚴格,當一個事務A在讀取一個值的時候
            是不允許另一個事務對該值進行修改的;
            為了允許重復讀取,可以選用該級別,因為TRANSACTION_READ_
            COMMITED這個事務級別,是允許重復讀取提交的數據的,如果
            事務A在讀取一個數值的時候,值為"Hello World!",但這個時
            候事務B對"Hello World"值進行修改了,改為"Hello EveryOne"
            然后提交,當事務A再次去讀取這個值的時候,去發現原來讀到
            的值改變了,變成了"Hello EveryOne",為了防止出現這種情況
            可以禁止重復提交,目的是為了重復讀取不會出錯!那么這個
            時候就可以選擇
          TRANSACTION_REPEATABLE_READ這個級別,
            這個級別就是用來禁止重復提交的.
          (實際上是加了行鎖,鎖定了選中的數據,不允許修改,但是允許插入新的數據)
            雖然這個時候是禁止了重復提交,但卻可以添加刪除,
            比如事務A,作了個查詢語句"select * from 無名氏 "; 這個時候是允許事務B做這樣的操作的:
            "insert into 無名氏 values(2,'aaa')"; 這個時候,
            事務A再次做讀取操作的時候,卻發現數據莫名其妙的
            多了一條,這就是所謂的---幻影讀取;




           禁止幻讀(TRANSACTION_SERIALIZABLE):
           事務的最高級別(串行化  操作)事務級別最高,所耗費的性能也越多.
            禁止幻讀禁止了臟讀,禁止了重復提交和幻讀.
            也就是當事務A在按條件查詢的時候,事務A一旦沒有提
            交,任何事務都不能對事務A的資源進行操作--- 保證
            事務A的操作真正的原子性!


           注意:在Oracle中只支持兩種級別:

            TRANSACTION_READ_COMMITTED(默認的級別)(只有提交后
               才可以讀取)而每一個終端進行自己的DML操作 都自動開啟了一個事務

            TRANSACTION_SERIALIZABLE(竄行化操作)

          posted @ 2008-03-05 09:34 曉宇 閱讀(325) | 評論 (0)編輯 收藏

          字符串池

          Java運行環境有一個字符串池,由String類維護。執行語句String str="abc"時,首先查看字符串池中是否存在字符串"abc",如果存在則直接將"abc"賦給str,如果不存在則先在字符串池中新建一個字符串"abc",然后再將其賦給str。執行語句String str=new String("abc")時,不管字符串池中是否存在字符串"abc",直接新建一個字符串"abc"(注意:新建的字符串"abc"不是在字符串池中),然后將其付給str。前一語句的效率高,后一語句的效率低,因為新建字符串占用內存空間。String str = new String()創建了一個空字符串,與String str=new String("")相同。

          public String intern()
          返回字符串對象的規范化表示形式。

          一個初始為空的字符串池,它由類 String 私有地維護。

          當調用 intern 方法時,如果池已經包含一個等于此 String 對象的字符串(用 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,并返回此 String 對象的引用。

          它遵循以下規則:對于任意兩個字符串 st,當且僅當 s.equals(t)true 時,s.intern() == t.intern() 才為 true

            String.intern();
          再補充介紹一點:存在于.class文件中的常量池,在運行期間被jvm裝載,并且可以擴充。String的intern()方法就是擴充常量池的一個方法;當一個String實例str調用intern()方法時,java查找常量池中是否有相同unicode的字符串常量,如果有,則返回其引用,如果沒有,則在常量池中增加一個unicode等于str的字符串并返回它的引用。
          例3:
          String   s0=”kvill”;
          String   s1=new   String(“kvill”);
          String   s2=new   String(“kvill”);
          System.out.println(s0==s1);
          S1.intern();
          S2=s2.intern();
          System.out.println(s0==s1);
          System.out.prntln(s0==s1.intern());
          System.out.println(s0==s2);
          結果為:
          False
          False   //雖然執行了s1.intern(),但它的返回值沒有賦給s1
          True
          True
          最后再破除一個錯誤的理解:
          有人說,“使用String.intern()方法可以將一個String類保存到一個全局的String表中,如果具有相同值的unicode字符串已經在這個表中,那么該方法返回表中已有字符串的地址,如果在表中沒有相同值的字符串,則將自己的地址注冊到表中”如果把這個全局的String表理解為常量吃的話,最后一句話“如果在表中沒有相同值的字符串,則將自己的地址注冊到表中”是錯的。
          例4:
          String   s1=new   String(“kvill”);
          String   s2=s1.intern();
          System.out.println(s1==s1.intern());
          System.out.println(s1+”   ”+s2);
          System.out.println(s2==s1.intern());
          結果是:
          False
          Kvill   kvill
          True
          我們沒有聲明一個”kvill”常量,所以常量池中一開始沒有”kvill”的,當我們調用s1.intern()后就在常量池中新添加了一個”kvill”常量,原來的不在常量池中的”kvill”仍然存在,也就不是“把自己的地址注冊到常量池中”了。
          例5:
          String   str1=”java”;
          String   str2=”blog”;
          String   s=str1+str2;
          System.out.println(s==”javablog”);
          結果是false。Jvm確實對型如String   str1=”java”;的String對象放在常量池里,但是它是在編譯時那么做的,而String   s=str1+str2;是在運行時刻才能知道,也就是說str1+str2是在堆里創建的,所以結果為false了。


          比較兩個已經存在于字符串池中字符串對象可以用"=="進行,擁有比equals操作符更快的速度

          posted @ 2008-03-04 09:40 曉宇 閱讀(845) | 評論 (0)編輯 收藏

          JAVA中的異常處理

          在JAVA中,如果某個方法不能夠按照正常的途徑完成它的任務,就可以通過另外一個途徑退出方法。在這種情況下,方法并不立刻返回,而是拋出一個封裝了錯誤信息的對象。需要注意的是,這個方法將會立刻退出,且并不返回正常情況下的值。此外,調用這個方法的代碼也將無法執行,取而代之的是,異常處理機制開始搜索能夠處理這種錯誤條件的異常處理器。

          如果在子類中覆蓋了超類的一個方法,那么子類方法聲明的已檢查異常不能超過超類方法中聲明的異常圍。(也就是說子類中拋出的異常范圍更小或者根本不拋出異常)。需要說明的是,如果超類方法沒有拋出任何異常,子類也不能拋出任何已檢查異常。例如,如果覆蓋JComponent.paintComponent()方法,那么    由于超類中沒有拋出任何異常,所以自定義的paintComponent()方法也不能拋出任何異常。

          如何拋出異常:
          譬如在讀一個輸入流時,如果期待的字節數為1024,而當讀到700字節的時候遇到一個EOF信號,這是我們未預期的,正是我們要拋出的異常,下面就是拋出改異常的語句

          1String readData() throws EOFException {
          2   while ({
          3      if(!in.hasNext()) {
          4          if(n<len)
          5            throw new EOFException();
          6     }
            
          7  }

          8}

          這是拋出已存在標準的異常,步驟為:
          1.找到一個合適的異常類
          2.創建該類的對象
          3.將異常拋出
          一旦拋出異常,該方法就不可能返回到調用者,這就意味著不必為返回的默認值或錯誤代碼擔憂了。

          在程序中可能會遇到任何標準異常都無法正確描述清楚的問題,這時候就需要定義自己的異常類,定義自己的異常類需要繼承自Exception 或者其子類,如繼承自IOException  一般要為自定義的Exception定義兩個構造函數,一個是默認的無參的構造函數,另一個是帶一個描述詳細錯誤信息String的構造函數(超類的toString()方法會打印出這些詳細信息。

          1public class MyException extends IOException {
          2
          3    MyException () {}
          4    
          5    MyException (String info) {
          6       super(info);
          7   }

          8}

          現在就可以像使用標準Exception類一樣使用自定義的Exception類了

          1String readData() throws MyException {
          2   while () {
          3      if(!in.hasNext()) {
          4          if(n<len)
          5            throw new MyException();
          6    }
            
          7 }

          8}

          可以用超類Throwable類的getMessage方法得到詳細的錯誤描述信息。或者toString()方法打印該信息。

          捕獲異常:
          如果語句exp1有可能拋出一個異常,或者說是調用了能夠拋出一個異常的方法,那么我們可以在程序中捕獲該異常

          1try {
          2 exp1;
          3 exp2;
          4 .
          5
          6}
           catch(Exception e) {
          7   e.
          8}

          9

          或者是并不捕獲,再次拋出該異常

          再次拋出異常,異常鏈:
          可以在catch塊中再次拋出新的異常,這樣可以隱藏原始的錯誤細節

          1catch(SQLException sqle) {
          2    throw new ServletException("caused by SQLException "+e.getMessage());
          3}

          另一種更好的方法
          既拋出高級的異常,又不會丟失原始的異常信息。

          1}catch(SQLException sqle) 
          2    Throwable ta=new ServletException("caused by SQLException");
          3    ta.setCause(e);
          4    throw ta;
          5}

          6當捕獲拋出的異常ta時,可以用ta.getCause(),得到原始的異常


          finally子句,發生三種情況時,會執行finally子句
          1.try代碼正常執行
          2.try代碼拋出一個在catch子句中捕獲的異常
          3.try代碼拋出一個未在catch子句中捕獲的異常
          就是說無論異常如何,finally子句中的代碼都會執行
          一般把一些資源回收的工作交給finally子句

          最好把try-catch塊和try-finally塊分開,這樣可以提高代碼的清晰度

           1try {
           2   try {
           3      //可能拋出IOException的語句
           4    }
           finally {
           5    is.close();
           6 }

           7}
           catch(IOExceotion e) {
           8   
           9}

          10

          這樣的另外一個好處是,可以catch到finally子句中拋出的異常。這也就引發了另外一個問題,如果在try和finally中都拋出了異常,而且是不同類型的,那么最后返回的是那一個呢?答案是finally中拋出的異常會覆蓋try中拋出的異常。從而丟失了try當中拋出的異常信息,讓拋出該方法的使用者不能跟蹤異常信息。所以,在finally中執行的語句最好是不要拋出異常,但是不幸的是我們有時候不得不在finally中執行一些清楚操作如:關閉輸入流InputStream,但是InputStream類的設計者并沒有這么設計(將會拋出異常)。

          由于finally子句總是會執行,所以在finally中包含return值時,是很危險的。假設我們利用return語句從try中返回,在方法返回之前finally子句的內容將會被執行。如果finally子句當中也包含一個return 語句,那么這個return語句所返回的值,將會覆蓋原先return的值。

          1public int f(int n) {
          2  try {
          3      return n*n;
          4    }
           finally {
          5     if(n==2)
          6       return 2;
          7  }

          8}

          在這里如果調用i=f(2);那么i的值將會是2而不是期望的2*2=4


          最后最重要的一點,關于一個方法是捕獲一個異常還是拋出給調用他的方法
          有一點規則   
                                          早拋出,晚捕獲,盡量把異常拋出給調用它的函數

          posted @ 2008-02-26 14:05 曉宇 閱讀(530) | 評論 (0)編輯 收藏

          JAVA 的字符編碼的問題

          首先講一講字符集
           JDK1.4版本引入了java.nio包加入了Charset類來統一字符集的轉換,字符集給出了雙字節Unicode碼序列與本地字符編碼中采用的字節序列之間的映射
          字符集的名稱不區分大小寫,可以用官方名稱或者任何一個別名調用靜態方法forName來獲得Charset

          1Charset charset=Charset.forName("GBK");
          Charset的aliases()方法返回一個Set<String>集合,表示該字符集所具有的所有別名
          Set<String> aliases=charset.aliases();
          查看虛擬機所支持的字符集以及名字可用Charset的靜態方法availableCharsets()返回一個SortedMap
          1 Map<String,Charset> map=Charset.availableCharsets();
          2            for(String setname:map.keySet()) {
          3                System.out.println(setname);
          4            }
          一旦有了字符集,就可以用他在本地字符串和Unicode字節序列之間轉換
          如下將一個字符串編碼為gbk    charset.encode(str)函數返回一個ByteBuffer對象
          1String str=new String("曉宇");
          2            ByteBuffer  buff = charset.encode(str);
          3            byte[] bytes=buff.array();
          同樣,可以將剛才按照GBK方式編碼的字節流解碼為正確的字符流
          1ByteBuffer by=ByteBuffer.wrap(bytes, 0, bytes.length);
          2      CharBuffer cb=charset.decode(by);//返回一個CharBuffer對象,已經將字節數組轉化為字符數組
          3      System.out.println("  "+cb.toString());


          實際上String類中集成了Charset對象的使用,String類有兩個用于編碼和解碼的函數

          1byte[] bytes = str.getBytes("CharsetName");  //將字符串str按照指定名稱的Charset進行編碼成字節數組
          2            String str2=new String(bytes,"CharsetName"); //將字節數組按照指定名稱的Charset解碼為字符串


          在輸入輸出流中有兩個用于將字節流轉化為指定編碼格式的字符流的類  InputStreamReader/OutputStreamReader
          這兩個類是讀寫流和讀寫器的橋梁 用法如下

          1InputStreamReader isr = new InputStreamReader(in, "charsetname");
          2            BufferedReader br = new BufferedReader(isr);//加入一個BufferedReader,可以用到該類的readLine()

          該用法在我的另外一篇socket備忘的里面體現了,可將網絡傳過來的utf-8格式編碼的字節流正確的解碼,以至于顯示的時候不會出現亂碼





          posted @ 2008-02-24 16:44 曉宇 閱讀(521) | 評論 (0)編輯 收藏

          SOCKET基礎 學習筆記

               摘要:     1package com;   2   3import java.io.BufferedReader;   4import java.io.ByteArrayOutputStream;   5import java.io.Filte...  閱讀全文

          posted @ 2008-02-22 16:26 曉宇 閱讀(240) | 評論 (0)編輯 收藏

          字節數組和其他類型的轉換

           

          //整數到字節數組的轉換 軟件測試專業網站:51Testing軟件測試網 h$_g8Lbx g s
             public byte[] intToByte(int intValue) {
          O R-v0OS&{;u0    byte[] result = new byte[4];
          e!sm#DN0    result[0] = (byte) ( (intValue & 0xFF000000) >> 24);軟件測試專業網站:51Testing軟件測試網3e Ou-l*l
              result[1] = (byte) ( (intValue & 0x00FF0000) >> 16);軟件測試專業網站:51Testing軟件測試網%F3hN!XoC
              result[2] = (byte) ( (intValue & 0x0000FF00) >> 8);
          d"TS)ro;L`;A:eI0    result[3] = (byte) ( (intValue & 0x000000FF));軟件測試專業網站:51Testing軟件測試網t1^O{;_,S"e `
              return result;軟件測試專業網站:51Testing軟件測試網q*~[? n M"i
            }

            //字節數組到整數的轉換 軟件測試專業網站:51Testing軟件測試網i f9``3@0LZK&R
            public static int byteToInt(byte[] b) { 軟件測試專業網站:51Testing軟件測試網Rb~,Ws"u1m
          public static int byteToInt(byte[] byteVal) {
          2X/cH bIM0      int result = 0;軟件測試專業網站:51Testing軟件測試網7e5~3p"J r\ _
                for (int i = 0; i < byteVal.length; i++) {
          1i {T q a2eT V_.^!Q0        int tmpVal = (byteVal[i] << (8 * (3 - i)));
          &?x%pQ4_9T7k0        switch (i) {軟件測試專業網站:51Testing軟件測試網A P/u[ C,J&FA#f
                    case 0:軟件測試專業網站:51Testing軟件測試網B,}\z`]8UU
                      tmpVal = tmpVal & 0xFF000000;軟件測試專業網站:51Testing軟件測試網*yS6X$y9n*md~
                      break;
          piL/jY)lkZ?0          case 1:軟件測試專業網站:51Testing軟件測試網5D#YS%w3f X|g
                      tmpVal = tmpVal & 0x00FF0000;軟件測試專業網站:51Testing軟件測試網c?Iu I w
                      break;軟件測試專業網站:51Testing軟件測試網~&E3Vmp0_;}@
                    case 2:
          6j3t1F;iX+K4{0            tmpVal = tmpVal & 0x0000FF00;軟件測試專業網站:51Testing軟件測試網5fD7H.i y R a/q
                      break;
          ]5b:h MMa!K0          case 3:
          )^~_.\A0            tmpVal = tmpVal & 0x000000FF;
          t2}8J f7A E~eH2[0            break;軟件測試專業網站:51Testing軟件測試網\? d:MN#D#iN
                  }
          MJ:c.rxWE0X"e"^*@0        result = result | tmpVal;軟件測試專業網站:51Testing軟件測試網9R lE\Q(g&SAJ
                }軟件測試專業網站:51Testing軟件測試網1ixe#~9]lyF},T
                return result;軟件測試專業網站:51Testing軟件測試網d,d"L^/fC?*upX
              }

            //字符到字節轉換
          Q N"P6tq.b@~0  public static byte[] charToByte(char ch){ 軟件測試專業網站:51Testing軟件測試網%]|X,~-vb'?$SU
              int temp=(int)ch; 軟件測試專業網站:51Testing軟件測試網'L9cx"B:` Ak
              byte[] b=new byte[2]; 軟件測試專業網站:51Testing軟件測試網2C8j1U/i1[ ls
              for (int i=b.length-1;i>-1;i--){
          'C3^]_V:qz0      b = new Integer(temp&0xff).byteValue();      //將最高位保存在最低位 軟件測試專業網站:51Testing軟件測試網 |S`"I h%YQU\(g
                temp = temp >> 8;       //向右移8位 軟件測試專業網站:51Testing軟件測試網!s/jv'Z2R
              } 軟件測試專業網站:51Testing軟件測試網R+C:w4LY4Xu!M
              return b; 軟件測試專業網站:51Testing軟件測試網%n+x/Y ZV`6T\
            }

            //字節到字符轉換 軟件測試專業網站:51Testing軟件測試網n:gg'^!_@NF p*@B
            public static char byteToChar(byte[] b){ 軟件測試專業網站:51Testing軟件測試網(}xOQ:b
              int s=0;
          ZuYw~ac0    if(b[0]>0) 軟件測試專業網站:51Testing軟件測試網'Tsc(rq
                s+=b[0]; 軟件測試專業網站:51Testing軟件測試網5G]%j*fg)wk$Z
              else 軟件測試專業網站:51Testing軟件測試網q#i2kb@
                s+=256+b[0];
          #iCo0kd+|i0    s*=256; 軟件測試專業網站:51Testing軟件測試網X%Zn?-k9h5q
              if(b[1]>0) 軟件測試專業網站:51Testing軟件測試網(E0v"C(Bv4Q
                s+=b[1];
          +{`z$m a R0    else 軟件測試專業網站:51Testing軟件測試網D^j aODKA3T
                s+=256+b[1]; 軟件測試專業網站:51Testing軟件測試網\ hv8We}U)b
              char ch=(char)s; 軟件測試專業網站:51Testing軟件測試網#JLO"h;NH*AHb0LLt!m
              return ch; 軟件測試專業網站:51Testing軟件測試網$g,Mu0?JT#Ef&xi
            }

            //浮點到字節轉換
          de4w8L-MpD8{\0  public static byte[] doubleToByte(double d){ 軟件測試專業網站:51Testing軟件測試網,~9g3FuQ9q;sMCa
              byte[] b=new byte[8]; 軟件測試專業網站:51Testing軟件測試網 UY:}1oV:\ {-uZ7Ed
              long l=Double.doubleToLongBits(d);
          ar8f3|"@b(g'L0    for(int i=0;i<b.length;i++){
          %t4roUTU;zgxI0      b=new Long(l).byteValue(); 軟件測試專業網站:51Testing軟件測試網*I%@7R#} bb0P
                l=l>>8;
          E$^+\"u!h!Y3^0    } 軟件測試專業網站:51Testing軟件測試網%])x)S)u)i,ul
              return b;
          n`(]3K k`0  }

            //字節到浮點轉換
          KwV!^Kt2q#p j0  public static double byteToDouble(byte[] b){
          :C.}9o GI9r0    long l;

              l=b[0]; 軟件測試專業網站:51Testing軟件測試網^4_/j4oL\*l b
              l&=0xff; 軟件測試專業網站:51Testing軟件測試網8x-fA;H.\
              l|=((long)b[1]<<8); 軟件測試專業網站:51Testing軟件測試網P\Z9tk
              l&=0xffff;
          u;A&Vs3n.p]*K/B0    l|=((long)b[2]<<16);
          )_ ^,F\ n3o0    l&=0xffffff;
          ` z3~*PIe aMK0    l|=((long)b[3]<<24);
          DM!ldb&|U(A*J0    l&=0xffffffffl;
          'i)k yh\0    l|=((long)b[4]<<32); 軟件測試專業網站:51Testing軟件測試網 T$D_Wr:M!_,E^a
              l&=0xffffffffffl;

              l|=((long)b[5]<<40); 軟件測試專業網站:51Testing軟件測試網g3m+GN$_)J1h,F.^(u.H d
              l&=0xffffffffffffl;
          ,gJ&o'u N7\Sp0    l|=((long)b[6]<<48);
          :m@s7\WCt+B0    l&=0xffffffffffffffl;
          ,x)T:eO e2d![0    l|=((long)b[7]<<56);
          }^MS.x%_7P0    return Double.longBitsToDouble(l); 軟件測試專業網站:51Testing軟件測試網Q)at;{k9Tq
            }

          posted @ 2008-02-22 15:06 曉宇 閱讀(756) | 評論 (0)編輯 收藏

          TREEMAP的排序機制

               摘要: 1package com.sf;  2  3import java.text.CollationKey;  4import java.text.Collator;  5import java.util.Comparator;  6import java.util.Map;  7...  閱讀全文

          posted @ 2008-02-19 15:16 曉宇 閱讀(2104) | 評論 (1)編輯 收藏

          HASHTABLE的內部實現

           

          public class TestHashtable {
              
          public static void main(String[] args){
                  Hashtable ht 
          = new Hashtable();
                  ht.put(
          "sichuan","chengdu"); //改變以下四行代碼的順序,可能會改變輸出內容的順序    
                  ht.put("hunan","changsha");     
                  ht.put(
          "beijing","beijing");    
                  ht.put(
          "anhui","hefei");    
                  
              Enumeration e 
          = ht.keys();
              
          while(e.hasMoreElements()) {
                  Object key 
          = e.nextElement();
                  Object value 
          = ht.get(key);            
                  System.out.println(key 
          + " " + value + " " + key.hashCode() + " " + value.hashCode());
              }

                  
              }

          }

           為了講述Hashtable鍵排序的問題,我們先來看Hashtable的結構圖:

          Hashtable.GIF

                  從上面的結構圖可以看出,Hashtable的實質就是一個數組+鏈表。圖中的Entry就是鏈表的實現,Entry的結構中包含了對自己的另一個實例的引用next,用以指向另外一個Entry。而圖中標有數字的部分是一個Entry數組,數字就是這個Entry數組的index。那么往Hashtable增加鍵值對的時候,index會根據鍵的hashcode、Entry數組的長度共同決定,從而決定鍵值對存放在Entry數組的哪個位置。從這種意義來說,當鍵一定,Entry數組的長度一定的情況下,所得到的index肯定是相同的,也就是說插入順序應該不會影響輸出的順序才對。然而,還有一個重要的因素沒有考慮,就是計算index出現相同值的情況。譬如代碼中 "sichuan" 和 "anhui",所得到的index是相同的,在這個時候,Entry的鏈表功能就發揮作用了:put方法通過Entry的next屬性獲得對另外一個Entry的引用,然后將后來者放入其中。根據debug得出的結果,"sichuan", "anhui"的index同為2,"hunan"的index為6,"beijing"的index為1,在輸出的時候,會以index遞減的方式獲得鍵值對。很明顯,會改變的輸出順序只有"sichuan"和"anhui"了,也就是說輸出只有兩種可能:"hunan" - "sichuan" - "anhui" - "beijing"和"hunan" - "anhui" - "sichuan" - "beijing"。以下是運行了示例代碼之后,Hashtable的結果:

          Hashtable1.GIF

              
                  以上的討論基于Java展開的,在C#中的Hashtable實現會有所不同,但是我相信兩者的設計應該是差不多的。感謝葉漂
          和quitgame,給了我思考的機會,也讓我感到了基礎知識的匱乏,看來是要補補基礎知識了。   

                  [補充]:在Hashtable的實現代碼中,有一個名為rehash的方法用于擴充Hashtable的容量。很明顯,當rehash方法被調用
          以后,每一個鍵值對相應的index也會改變,也就等于將鍵值對重新排序了。這也是往不同容量的Hashtable放入相同的鍵值對會輸出不同的鍵值對序列的原因。在Java中,觸發rehash方法的條件很簡單:hahtable中的鍵值對超過某一閥值。默認情況下,該閥值等于hashtable中Entry數組的長度×0.75

          posted @ 2008-02-19 11:07 曉宇 閱讀(1663) | 評論 (0)編輯 收藏

          JDBC中的連接方式 thin模式 和 DataSource方式

          一、最常用的是thin模式   利用DriverManager得到Connection
          Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); 
          String url
          ="jdbc:oracle:thin:@localhost:1521:orcl"//orcl為數據庫的SID 
          String user="test"
          String password
          ="test"
          Connection conn
          = DriverManager.getConnection(url,user,password);

          二、JDBC的另外一種方式是三層結構,就是在應用服務器(tomcat/weblogic)上面建立DataSource
          1Context ctx=new InitiaContext(Hashtable env);
          2DataSource ds=(DataSource)ctx.lookUp("jdbc/OraDB");
          3Connection con=ds.getConnection();

          應用中配置如下:未測試,僅轉載。
             
          一、配置server.xml
          找到配置發布應用程序的地方:<Context path=”” docBase=”d:\_webs”/>
          將這個改為:
          <Context path="" docBase="D:\ _web" debug="0">
           
          <!—聲明一個數據源,程序通過JNDI找到該數據源。
          name指出數據源的名稱為jdbc/OraDB,
          auth表明連接池管理的權限,
          type指出該數據源的類型-->
          <Resource name="jdbc/OraDB" auth="SERVLET" type="javax.sql.DataSource"/>
           
          <!—配置該數據源的屬性
          name指出數據源的名稱
          -->
          <ResourceParams name="jdbc/OraDB">
           
          <!—連接數據庫的用戶名-->
          <parameter>
          <name>username</name>
                     <value>chenws</value>
          </parameter>
              
           <!—連接數據庫的密碼-->
           <parameter>
                     <name>password</name>
                  <value>admin</value>
           </parameter>
                     
           <!—連接數據庫的jdbc驅動程序-->
           <parameter>
                     <name>driverClassName</name>
                     <value>oracle.jdbc.driver.OracleDriver</value>
           </parameter>
           
            <!—連接數據庫的url-->
           <parameter>
                     <name>url</name>
                     <value>jdbc:oracle:thin:@192.168.39.215:1521:jetchin</value>
           </parameter>
          </ResourceParams>
                  
          </Context>
           
          實際上,配置數據源的屬性不止以上那些,還有其他的比如連接時間的限制,連接數量的限制等等。這里我們并沒有給出,只是使用了tomcat提供的默認屬性罷了。
          注意:要讓該數據源有效,必須將oracleclasses12.zip改名為classes12.jar,然后拷貝到
          tomcat安裝目錄下的/common/lib中。
           
          二、配置web.xml
          web應用程序目錄下的web-inf中,打開web.xml,加入如下的配置:
          定義數據源參照:
          <resource-ref>
           <!—數據源描述,可有可無-->
           <description>Oracle Datasource example</description>
           
            <!--數據源名稱-->
           <res-ref-name>jdbc/OraDB</res-ref-name>
           
            <!—數據源類型-->
          <res-type>javax.sql.DataSource</res-type>
           
           <!—連接池管理權限-->
           <res-auth>SERVLET</res-auth>
          </resource-ref>


          另外在weblogic中進行配置可參考如下文章:


          WebLogic Server7.0中Oracle的JDBC Pool/DataSource配置指南
           
           

          第一步,去oracle下載最新的 oracle JDBC driver。

          一共2個文件,ojdbc14.jar和nls_charset12.zip。
          第一個文件是驅動程序所在,第二個是支持國際化的包。

          接下來,把這兩個文件加入 WLS 的 classpath。
          修改 Bea\Weblogic\server\bin\startWLS.cmd(或者相應的Unix啟動文件,.sh結尾的),

          在文件開頭加入 PRE_CLASSPATH=C:\ojdbc14.jar;C:\nls_charset12.zip。注意文件的路徑。

          最后可以考慮把Bea\Weblogic\server\lib\classes12.zip刪除,我不保證正確性,只是怕有兼容性問題。

          最后,啟動weblogic server,進入console,在Connection Pool里邊,填入一下資料。

          General欄目:

          Name:MyOracle_CP

          URL:jdbc:oracle:thin:@server:port:sid (自己按照情況修改!)
          比如:jdbc:oracle:thin:@192.168.0.2:1521:Crystal

          DriverName:oracle.jdbc.driver.OracleDriver

          Properties
          user=SYS (這里是用戶,最好不要用SYS,SYSTEM等系統用戶)

          ACL Name: (空)

          password: 用戶密碼

           


          如圖:



          Connection欄目:


          CapacityIncrement = 50
          MaxCapacity = 100
          Capacity Increment: 5
          Login Delay Seconds: 0 seconds
          Refresh Period: 10 minutes
          Supports Local Transaction 不要打勾
          Allow Shrinking 打勾
          Shrink Period: 15 minutes
          Prepared Statement Cache Size: 5

          如圖:



          Test欄目:

          TestTableName:SCOTT.EMP (這里需要改動,適應你自己的表,wls用來做連接測試用的)
          TestConnectionsOnReleasetrue 打勾
          TestConnectionsOnReservetrue 打勾

          最后,點擊Apply,然后去Targets,選中你的server,點右箭頭,使你的server進入Chosen欄目,最后Apply。(如圖)




          查看dos窗口,是否有錯誤,如果沒有則繼續,如果有的話,自己查看填寫的內容。

          至此,Connection Pool已經配置完畢。


          接下來,該配置(TX)DataSource了。

          從昨天的panel里邊,單擊DataSources/TX DataSources,進入配置界面。

          1。單擊Configure a new JDBC Tx Data Source..配置新的datasource

          2。填入以下數據:
          Name: MyDataSource (自己隨便起的)
          JNDI: jdbc/OracleDS (這里就是你lookup的時候填入的名字,自己想吧。
          Pool Name: MyOracle_CP (一定要對應你的Connection Pool的 Name)

          把后邊兩項打上勾。

          第一個是模擬2階提交模式,如果數據庫driver本身不支持的話。(就是XA標準,分布式提交)

          第二個是 行預讀。如圖:

           

           

           

           

           

           

           

           

           

           

           

           

          點擊Create,然后去Targets里邊,把你的 server放入chosen,點擊apply。。

          配置完成。。。

          最后檢查你的DataSource是否已經成功部屬:

          進入你的server的JNDI Tree,很容易就可以看到的。:)。如圖:





          posted @ 2008-02-19 10:22 曉宇 閱讀(3727) | 評論 (0)編輯 收藏

          JDBC中的批處理

          JDBC中 有兩個批處理函數  addBatch(String)  和 executeBatch();

          有兩種方法可以進行批處理 第一種是用Statement  另外一種是PreparedStatement

          一、使用Statement 

           

          1Statement sm=con.createStatement();
          2String sql="insert into errbills values()";
          3sm.addBatch(sql);
          4sql="delete from errbills where bno='124'";
          5sm.addBatch(sql);
          6sm.executeBatch();


          二、使用PreparedStatement

          1String sql="delete from errblls where bno=?";
          2PreparedStatement ps=con.prepareStatement(sql);
          3for(int i=0;i<10;i++{
          4   ps.setString(i);
          5   ps.addBatch();
          6}

          7ps.executeBatch();
          8

          注意使用Statement和PreparedStatement的區別  Statement的addBatch(String s)是帶參數的(所要執行的SQL語句) 而PreparedStatement是不帶參數的

          在JDBC中使用批處理可以提高執行速度,因為我們不需要維護多條語句,所有的操作都是在一條語句里面完成,這樣數據庫服務器不必要為每條語句都分配和維護資源(指針等),可以減輕數據庫服務器的壓力

          posted @ 2008-02-19 09:50 曉宇 閱讀(536) | 評論 (1)編輯 收藏

          僅列出標題
          共4頁: 上一頁 1 2 3 4 下一頁 
          主站蜘蛛池模板: 石柱| 彰化市| 巨野县| 福鼎市| 务川| 西城区| 诸城市| 永泰县| 邵东县| 福清市| 鄱阳县| 漠河县| 和田市| 南宁市| 新泰市| 宁安市| 黔西县| 黄石市| 衡水市| 长岛县| 宽甸| 上犹县| 密云县| 嘉兴市| 奇台县| 江油市| 大厂| 台安县| 南雄市| 松桃| 东乌| 石家庄市| 集安市| 闸北区| 乌拉特后旗| 百色市| 泸溪县| 龙岩市| 青龙| 广东省| 黎城县|