posts - 3,  comments - 2,  trackbacks - 0

          JDBC高級(jí)應(yīng)用

          轉(zhuǎn)自 http://www.blogcn.com/user69/galiasun/index.html


          本來(lái)想繼續(xù)談JDBC的高級(jí)連結(jié)方式,事務(wù)模式.但發(fā)現(xiàn)關(guān)于大對(duì)象存儲(chǔ)有很多人在問(wèn),所以
          先來(lái)插入一節(jié)關(guān)于大對(duì)象存儲(chǔ)的內(nèi)容,然后再接著原來(lái)的思路寫下去.

          JDBC的大對(duì)象存儲(chǔ)聽(tīng)起來(lái)復(fù)雜,其實(shí)如果你明白了原理以后,就非常簡(jiǎn)單,網(wǎng)上有關(guān)這方面的
          教材很少,而SUN的文檔中,我從1.2開(kāi)始看到一在仍然是錯(cuò)誤的,不知道寫文檔的人長(zhǎng)腦子沒(méi)
          有,就那幾行代碼你試試不就知道了,這么多次重抄下來(lái)還是錯(cuò)誤的.


          大對(duì)象分類:一般來(lái)說(shuō),大對(duì)象分為:大的文本對(duì)象,比如一個(gè)很長(zhǎng)的文本(請(qǐng)你要注意什么是
          文本文件,什么是二進(jìn)制文件)文件,或者是你定義的一個(gè)長(zhǎng)字符串,比如你定義了:
          String s = "我們要去吃飯了......................然后睡覺(jué)!";
          從吃飯到睡覺(jué)中間省略了實(shí)際的10000000000000字,雖然你不會(huì)真的定義這么稱的String,但
          有時(shí)會(huì)從什么地方得到這樣的String,要寫到數(shù)據(jù)庫(kù)中.
          另一種就是大的二進(jìn)制對(duì)象,象執(zhí)行文件,圖象文件等,注意,word,excel,ppt這些"帶格式"的文
          檔都應(yīng)該以二進(jìn)制對(duì)象存儲(chǔ).

          一般來(lái)說(shuō),數(shù)據(jù)庫(kù)如果支持大對(duì)象存儲(chǔ),會(huì)有這幾種類型的SQL數(shù)據(jù)類型:
          BLOB,CLOCB,NLOB,也有的數(shù)據(jù)數(shù)只有一種BLOB,基本上是這樣的:BLOB用來(lái)存放二進(jìn)制文件,而
          CLOB用來(lái)存放文本文件,NLOB是對(duì)多字節(jié)文本文件支持.假如你的文本文件是純英文的,放在
          BLOB中當(dāng)然可以,也就是說(shuō)它是以byte格式存儲(chǔ)的,而多字節(jié)是以CHAR格式存儲(chǔ)的.

          同樣對(duì)于這幾種類型的文檔,有幾種相對(duì)應(yīng)的存取方式:
          setter:
          利用PreparedStatement的setXXX方法,
          setAsciiStream()方法用于寫入一般的文本流.setBinaryStream()方法用于寫入二進(jìn)制流
          而setUnicodeStream()用于寫好UNICODE編碼的文本,與此相對(duì)應(yīng)的ResultSet中三個(gè)getter方法
          用于取回:getAsciiStream(),getBinaryStream(),getBinaryStream().
          對(duì)于文件本身,要把它作為一個(gè)流,只要new InputStream(new FileInputStream("文件路徑")
          就可以了,但對(duì)于大的String對(duì)象,你不會(huì)寫入文件再轉(zhuǎn)換成輸入流吧?
          new StringBufferInputStream(String s),記住了.
          JDBC2以后提供了java.sql.BLOB對(duì)象,我不建議大家使用它,一是很麻類,二是容易出錯(cuò),要先插
          入一個(gè)空的BLOB對(duì)象,然后再填充它,實(shí)在沒(méi)有必要,直接setXXX就行了,我試過(guò),至少mysql,
          oracle,sql server是可以直接set的.
          好了,我們先看一個(gè)例子如何寫入文件到數(shù)據(jù)庫(kù):
          數(shù)據(jù)結(jié)構(gòu):
          create table test(
            name varchar(200),
            content BLOB
          );
          File f = new File("a.exe";//先生成File對(duì)象是為了取得流的長(zhǎng)度.FileInputStram可以直接
                                     //傳入文件路徑
          InputStream in = new InputStream(new FileInputStream(f));
          PreparedStatement ps = conn.prepareStatement("insert into test (?,?)";
          ps.setString(1,"a.exe");
          ps.setBinaryStream(2,in,(int)f.length());
          ps.executeUpdate();
          f的長(zhǎng)度一定要做從long到int的轉(zhuǎn)換,SUN的文檔中好幾版都沒(méi)有改過(guò)來(lái).就這么簡(jiǎn)單,當(dāng)然,不同的
          數(shù)據(jù)庫(kù)存本身要設(shè)置它允許的最大長(zhǎng)度,MYSQL默認(rèn)只能傳1M的文件,要修改參數(shù)原能存更大的文件.
          如果要從數(shù)庫(kù)中取得文件:
          PreparedStatement ps = conn.prepareStatement("select * from test where name=?");
          ps.setString(1,"a.exe";
          ResultSet rs = ps.executeQuery();
          if(rs.next()){
           InputStream in = rs.getBinaryStream("content";
          }
          得到in對(duì)象后,你可以進(jìn)行任何處理,寫向文件和寫向頁(yè)面只是out對(duì)象不同而已:
          寫向文件:
          DateOutputStream out = new DateOutputStream(new FileOutputStream("b.exe");
          寫向頁(yè)面:
          response.reset();
          response.setContType("類型";
          ServletOutputSreamt out = response.getOutputSream();
          得到out對(duì)象后,就可以輸出了:
          byte[] buf = new byte[1024];
          int len = 0;
          while((len = in.read(buf)) >0)
            out.write(buf,0,len);
          in.close();
          out.close();
          對(duì)于向頁(yè)面輸入,要設(shè)置什么樣的ContType,要看你想如何輸出,如果你想讓對(duì)方下載,就設(shè)為
          "application/octet-stream",這樣即使是文本,圖象都會(huì)下載而不會(huì)在瀏覽器中打開(kāi).如果你要想
          在瀏覽器中打開(kāi),就要設(shè)置相應(yīng)的類型,還要在容器的配置文件中設(shè)置支持這種文檔類型的輸出,但
          對(duì)于很多格式的文件,到底要輸出什么類型,其實(shí)就是HTTP的MIME集,比如圖片:image/gif,當(dāng)然你如
          果你的文件擴(kuò)展名(ext)不確定,你也不要用if(ext.equals("gif")......這樣來(lái)判斷,我教你一個(gè)
          技巧,我之所以說(shuō)是技巧,是我沒(méi)有在別的地方發(fā)現(xiàn)有人用這種方法,對(duì)我來(lái)說(shuō)我是絕對(duì)不會(huì)把別人的
          方法拿來(lái)說(shuō)是我的技巧的:
          構(gòu)造一個(gè)file類型的URL,我們知道URL目前JAVA可以支持HTTP,FTP,MAILTO,FILE,LDAP等,從FILE類型
          的URL就可以得到它的MIME:

          URL u = new URL("file://a.exe";
          String mime = u.openConnection().getContentType();
          這樣你就可以直接response.setContType(mime);而不用一個(gè)一個(gè)類型判斷了.
          好了,大對(duì)象存儲(chǔ)就說(shuō)到這兒,不同的數(shù)據(jù)仍然和些特殊的規(guī)定,不在此一一列舉了.

          posted on 2007-08-03 00:40 Mr. Michael.Q 閱讀(306) 評(píng)論(0)  編輯  收藏 所屬分類: 站在他人的肩膀上
          主站蜘蛛池模板: 日照市| 太谷县| 兴安盟| 育儿| 房产| 克拉玛依市| 乳山市| 顺义区| 沭阳县| 隆子县| 临汾市| 图们市| 西安市| 博客| 英超| 宝鸡市| 策勒县| 山西省| 滦南县| 林西县| 航空| 息烽县| 壤塘县| 孟津县| 鄂尔多斯市| 丹阳市| 文水县| 呈贡县| 吉林市| 永登县| 天门市| 清水河县| 来宾市| 巴彦县| 桂平市| 米脂县| 辽源市| 旌德县| 陆丰市| 长顺县| 泾川县|