很多網友都不知道JDBC中如何操作Blob、Clob等對象,其實這是不難的!操作這些對象就象操作其它String、int一樣。不信!你就看下面的文章。下面的例子會帶你首先創建包含Clob、Blob對象的數據庫的表,然後寫入這些對象,最後再讀取並操作這些對象!
一、關於Derby
www.open-open.com是這樣介紹Derby的“Apache Derby 是一種高質量的、純 Java™ 的嵌入式關系數據庫引擎,IBM® 最近已將其捐獻給開放源碼社區。Derby 數據庫基於文件系統,具有高度的可移植性,並且是輕量級的,這使得它非常便於發布。”據說它的源代碼價值幾十億美元哦!我一般使用Derby,因為使用它可以很多其它開源數據庫不能完成的操作,它是一個與JDBC標准完全兼容的數據庫產品,再說它是IT界泰斗IBM的開源項目,能不去好好研究,多多學習嗎?!
下載該軟件你可以去www.open-open.com、www.sourceforge.net。下載下來後將其db-derby-10.XXXX-lib.zip解壓放到一個目錄下(看到了吧,基本都是jar文件,我放在c:\Derby目錄中),同時讓你的classpath中包含derby.jar文件,這樣我們就可以在程序中使用該庫了!
簡單講述path和classpath吧!設置path的目的是:當你使用java、javac、rmic命令時系統會到指定的path下查找這些.exe或.com文件然後執行它,我們要使用java中的這些工具,當然在path環境變量中要包含它們所在的目錄了。classpath也差不多,當你在java中要調用其它已經有的類時,必須包含該類所在的目錄,這樣就可以調用了!例如在使用javac編譯servlet時,sun提供的servlet的包必須在你的classpath中。
下面就開始我們的例子吧!
二、一個簡單例子
本例中先創建一個包含Blob和Clob對象的數據庫的表,然後向此表中寫入Blob和Clob對象,最後再將這些數據庫表中的數據讀出並處理。其中使用了PreparedStatement對象、運用了一些和IO相關的知識。我們在此程序裡使用了兩種流的處理方式。下面是源代碼:
import java.io.*;
import java.sql.*;
public class BlobClobExample {
public static void main(String[] args) {
try {
String url = "jdbc:derby:clobberyclob;create=true";
//Derby中的URL,後面是附加參數。表示數據庫中沒有此數據庫時,會自動建一個
//其它數據庫提供商的產品可以查閱其手冊
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
//加載驅動。關於加載驅動的細節,請閱讀本博客的《JDBC中驅動加載的過程分析(上)》
//和《JDBC中驅動加載的過程分析(下)》
//在數據庫Mysql的驅動加載時也建議在Class.forName()後,繼續調用newInstance()方法
2
//沒有本質區別
Connection conn = DriverManager.getConnection(url); //建立連接
Statement s = conn.createStatement(); //創建Statement對象
s.executeUpdate("drop table documents");
//這句是為了避免再次創建表documents
s.executeUpdate("CREATE TABLE documents(id INT, text CLOB(64 K) , photo Blob(1440 K))");
//以上就是創建包含Clob和Blob對象的表的過程
//和將一般的字段差不多,後面括號中代表該對象的大小,其語法為:
// CLOB (length [{{K |M |G}]) 表示長度為K、M、G等,沒有帶表示比特
conn.commit(); //提交操作
//以下是將本地文件中,本程序的源文件加載為一個流,用於向數據庫中寫入Clob字段
File file1 = new File("BlobClobExample.java");
int len1 = (int) file1.length();
InputStream fis1 = new java.io.FileInputStream(file1);
//以下是將當前源代碼目錄的子目錄“11”下的“1.JPG”文件加載為一個流,
//用於後面向數據庫中寫入Blob字段
File file2 = new File("c:\\11\\1.JPG");
int len2 = (int) file2.length();
InputStream fis2 = new FileInputStream(file2);
//以上兩個簡單吧!!
//創建一個PreparedStatement對象,用於批量插入內容
//使用PreparedStatement對象可以節省,數據庫編譯SQL指令的時間,
//因為在使用PreparedStatement對象時,該SQL語句是預先編譯好了,
//對於某些變化的參數使用占位符(Place Holder)代替
//這對於以後將要執行多次的同一操作,該操作僅僅是參數不同,是極其有利
//比如在網頁上輸入客戶信息時,用戶要填入的數據基本是一樣的(你可以填也可以不填)
//這時後台的數據庫可以使用PreparedStatement對象,每次都是設置參數,執行操作
PreparedStatement ps = conn.prepareStatement("INSERT INTO documents VALUES (?, ?,?)");
ps.setInt(1, 250);
ps.setAsciiStream(2, fis1, len1);
ps.setBinaryStream(3,fis2,len2);
//以上三步是設置占位符的數值
ps.execute(); //執行操作
//以上四步可以重復執行。PreparedStatement就是為了適用於此用途
conn.commit();
//以上完成了數據的寫入
//以下是數據的讀出
ResultSet rs = s.executeQuery("SELECT text , photo FROM documents WHERE id = 250");
while (rs.next()) {
Clob aclob = rs.getClob(1); //和提取一般對象一樣
InputStream is = rs.getAsciiStream(1); //特殊的,對於與得到Clob的流
//這是得到Clob、Blob流的第一種方法
3
//以下是對流進行處理的過程。Clob本身是包含大字符的對象
//順其自然,以下是使用java IO中讀取字符流的方法讀取它
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null ;
while(null != (line = br.readLine())){
System.out.println(line); //將其輸出至屏幕,實際你可以按照需要處理
}
is.close();
java.sql.Blob ablob = rs.getBlob(2); //和操作其它基本類型的字段一樣
System.out.println(ablob.length()); //簡單地操作Blob的實例
//實際你可以使用Clob的API對其進行任何它允許的操作,請查API
InputStream bis = ablob.getBinaryStream() ; //得到Blob實例的字節流
//這是操作Clob、Blob等對象的第二種方法,也是最自然的用法
OutputStream os = new FileOutputStream("11.jpg");
//用於將數據庫中的Blob存放到目前目錄的“11.jpg”文件中
int b = bis.read(); //以下就是象操作其它java字節流一樣操作了
while (b != -1 ) {
os.write((char)b);
b = bis.read();
}
os.flush();
os.close();
bis.close();
}
} catch (Exception e) {
System.out.println("Error! "+e);
}
}
}
簡單吧!實際上寫入Blob和Clob對象時一般只能使用PreparedStatement對象,一般使用其setXXXStream寫入流。寫就是這麼簡單!看完了,研究一下API吧!讀出時一般通過getClob()、getBlob()方法,和其它提取基本數據類型字段的方法完全相同,接著你就可以得到此Clob、Blob實例的流了,有了流就可以象處理其它流一樣處理這些流了!
簡單吧!關鍵是一定要對基本流程了解!對其原來了解!對什麼IO、net、Collections….基礎知識必須精通!
運行的結果是本程序的源代碼會存儲在數據庫中,同時會在屏幕上顯式,源代碼目錄的子目錄“11”下的1.jpg會存儲到數據庫中,同時也會在當前目錄下有一個該文件的副本。(圖片的相對位置一定要搞對哦!)