摘要
Derby是一個100%Java開源的關系數據庫,并且你不可輕視它。
正文
一般的應用程序都需要一個簡單的存儲和獲得數據的方法。如果你長期開發一個軟件,你都需要一個關系數據庫為你長期服務。然而,作為一個Java開發者,你的選擇是有限的。你可能嘗試使用商業的關系數據庫管理系統,它們大多數不是用Java語言編寫的,雖然普遍的能達到100% Java JDBC連接器。這些商業產品通常需要大量的配置,接下來需要數據庫管理員對服務進行操作和調整,并且當你在每個客服端發布使用時,都需要很高的許可費。
另一方面,你可以選擇一個開源的Java基于關系數據庫管理系統實現。這些產品通常是為嵌入式應用設計的。支持有限的重要的標準SQL語句,并支持關系數據庫管理系統的最小特性。但是它們是自由許可的,容易管理,并且可以集成一些代碼來彌補缺少的特性。
它是一個理想的,并且開源的,100% Java編寫的,容易管理的關系數據庫管理系統,它可以和一些商業產品的特性進行交付。這篇文章是關注Apache Derby項目——一個兩全其美的關系數據庫管理系統。
Derby——一個出神入化的產品周期
圖片片刻實現一個商業級軟件產品的完美生命周期。最初,設計者應該開始構思;當設計師不能獲得問題的答案或沒有創新的解決方案時,將會喪失原有的激情。一旦產品能證明在解決問題上有自身的能力,并有一定數量的用戶基礎后,這個小公司將進入一個大公司的視野。使這款軟件成為它們收購的目標,大公司將“handen”這個產品附加質量保證,加寬它的范疇,使之快速增長,并寫出高質量的文檔。一旦這款產品達到它的最高采用時,然后大公司應該支持該產品成為開源項目,有一個很好的自由許可讓每個人都可以采用和修改。你,作為一個受益者可以獲得這些健壯的地層代碼,也可以將它加入到你的產品中,商業應用和其他的,并受益于探研地層代碼的所有心血。
當然,上面提到的理想化的軟件產品生命周期聽起來不會發生在資本主義自由經濟下。但是有時在現實生活中,是做得到的!
上面理想化的產品生命周期是確切的,因為它發生在Apache Derby上。Derby是一個名為Cloudscape的小公司構思的;當Cloudscape賣給Informix后,該產品得到了加強;當IBM加入時,在“big blue”期間,它的高端工程特性得到增強;現在已經成為一個有最自由的許可的開源項目而存在。
廣泛而深入的特性列表
Derby的生動逼真的撫育使得它擁有一個令人驚奇的特性列表。有許多簡單的高級特性不能被其他開源Java數據庫利用。一部分的列表特性使Derby從其他的Java 關系數據庫管理系統中分離出來,包括:
l 100% Java實現
l 100% Java類型4 JDBC驅動
l SQL92E標準支持大部分SQL 99特性
l ACID完全的事務獨立的事務支持
l J2EE支持JNDI,連接池和XA
l 視圖,臨時表和保存
l BLOB和CLOB數據類型
l 行和表鎖定
l 有價值的基本查詢優化
l 服務器端指示約束
l 觸發器和存儲過程
l 為服務器端函數,觸發器或存儲過程等操作在數據庫里存儲Java代碼
l 能排除CD-ROM里的只讀數據庫
l 數據的導入和導出
l 快速數據庫加密選項
在代碼例子中,你將談究使用指示約束,存儲過程和在數據庫中存儲Java代碼。
兩種靈活的使用模式
Derby可以工作在嵌入式模式下,或在完全的客戶端/服務器模式下。插圖1說明在嵌入式模式下的工作原理。
插圖1:嵌入式模式
在插圖1里,你可以看到Derby引擎是嵌入在你的應用程序里的。當工作在嵌入式模式,你的應用程序訪問數據庫是直接和專有的。這就意味著其他應用程序不可能在同一時間訪問該數據庫。嵌入式模式的主要優點是不需要進行網絡和服務器設置。因為你的應用程序包含了Derby引擎,使用者并不知道你使用了一個關系數據庫。
當使用Derby的嵌入式模式時,并沒有復雜的配置和特殊的API需要你去學習。實際上,你僅僅需要做:
1. 確保Derby JARs文件在你的應用程序classpath里
2. 使用嵌入式JDBC驅動
3. 寫數據庫訪問代碼到JDBC
這是正確的,Derby根本沒有特殊的APIs。只需要為你的應用程序編碼到JDBC,然后Derby會為你工作得很好。事實上,如果你已經有了JDBC代碼,而想把代碼轉換到Derby嵌入式模式下運行是十分容易的。
如果你使用過ORACLE,DB2,SQL Server或MySQL,你應該對網絡模式(客戶端/服務器模式)的工作原理相當熟悉。插圖2說明了這個模型的工作原理
插圖2:客戶端/服務器模式
在插圖2中,一個獨立的Java進程運行作為Derby的網絡服務器,通過網絡監聽客戶端的連接。該Derby網絡服務器能唯一的訪問數據庫存儲器,并能同時接受多個客戶端連接。這就允許多個用戶在同一時間通過網絡方式訪問該關系數據庫管理系統。
當不適合使用嵌入式模式進行操作時(例如:你必須運行和管理個別的服務器進程,或許在不同的機器上),當你需要多用戶訪問數據庫時,Derby的客戶端-服務器模式能提供一個有效的解決方案。
在插圖2中,注意客戶端應用程序編碼到JDBC。這些不是Derby特有的APIs。事實上,這個類似于插圖1里的運行在嵌入式下JDBC應用程序運行在客戶端-服務器模式的最低配置下。
配置Derby數據庫
為了完全體會Derby設置和使用的好處,你需要自己親身體驗它。首先,下載和安裝Derby。然后,確保你的classpath環境變量包含:
derby_installation_directory\lib\derby.jar;和derby_installation_directory\lib\derbytools.jar;
你也可以編輯提供給你的sp.bat文件,設置你的Derby安裝目錄,然后運行設置你的classpath。
一旦你設置好了classpath,就修改工作目錄。數據庫將被創建在這個目錄里面。從db\createdb目錄復制createdb.sql文件到工作目錄。然后,啟動命令行界面(執行ij)進入Derby:
java org.apache.derby.tools.ij
你也可以使用在batch子目錄下提供的ij.bat,在使用前一定要編輯該批處理文件,添加你的Derby安裝目錄路徑。這樣才能進入正確的命令行,使用嵌入式Derby引擎。你看到的提示將與下面的類似:
ij version 10.0
ij>
你可以輸入“help”;來查看可以使用的命令。要創建數據庫和表來使用,僅僅需要運行createdb.sql文件。使用ij命令:
run ‘createdb.sql’;
run命令將調用一個腳本文件并執行它里面的Derby命令,類似于Windows的批處理文件。下面顯示的是createdb.sql文件的內容。
connect
'jdbc:derby:vsjdb;create=true';
drop table orders;
drop table custs;
create table custs
(id char (5) not null,
name char(40) not null,
primary key(id));
create table orders
(id char(8) not null,
custid char(5) not null,
total integer,
primary key(id,custid));
insert into custs values (
'1', 'John Smith');
insert into custs values (
'2', 'Mary Todd');
insert into orders values(
'0001', '1', 39999);
insert into orders values(
'0002', '1', 2999);
insert into orders values(
'0003', '1', 1904);
insert into orders values(
'0004', '2', 3232);
insert into orders values(
'0005', '2', 109900);
在每一行都需要一個分號,這與命令行輸入命令是一樣的。腳本的第一行是連接命令,指明連接的嵌入式Derby驅動名字。在腳本里的連接命令為:
connect
‘jdbc:derby:vsjdb;create=true’;
使用jdbc:derby說明Derby驅動是使用的JDBC協議,而vsjdb是一個數據庫的名字,它能通過嵌入式驅動創建和訪問。create=true屬性說明如果該數據庫不存在時,就創建該數據庫。
該createdb.sql腳本將創建一個名為vsjdb(當它不存在時)的數據庫,并在該數據庫中創建custs和orders表。它將在表中添加兩個用戶和五個定單。如果你使用過其他數據庫的SQL語句,你應該相當熟悉在腳本里的SQL語句。
你可以查看你的工作目錄,現在你將看到一個vsjdb子目錄。數據將保存在里面。數據庫可以很簡單的的進行備份,就是復制這個子目錄。
表格1和表格2是custs和orders表的信息
Table 1: The custs table
|
Field Name
|
Data Type
|
Note
|
Id
|
char(5)
|
primary key
|
Name
|
char(40)
|
|
Table 2: The orders table
|
Field Name
|
Data Type
|
Note
|
Id
|
char(8)
|
primary key (compound)
|
Custid
|
char(5)
|
primary key (compound)
|
Total
|
int
|
|
與關系數據庫管理系統數據操作
要查看顧客記錄信息,在ij提示行后使用SQL SELECT語句:
select * from custs;
要查看定單,使用下面的命令:
select * from orders;
要刪除顧客,嘗試使用下面的命令:
delete from custs where id=’1’;
你可以選擇custs表里的某一行,并能查看到哪個用戶被刪除。要刪除與這個用戶相關聯的定單信息,使用下面的命令:
delete from orders where custid=’1’;
你現在可以查看orders表,并能看見所有關于一號顧客的定單都被刪除了。
在你離開ij前,刪除數據庫里的所有記錄:
delete from custs;
delete from orders;
著它將是一個空數據庫,在下一部分,將寫入自定義的Java代碼。
使用exit命令離開ij:
exit;
自從連接URL指定了嵌入式驅動,只有ij能唯一的訪問這個數據庫。
嵌入Derby到你的Java應用程序中
時間加速我們的Java編譯和編寫某些代碼。這些代碼將放入Derby做一個小測試,給你一個關系數據庫管理系統能處理現實世界大量數據能力的信心。
下面是名為FillTable.java的代碼,將創建1000個用戶,每個用戶有10條定單——總共10000條定單。在嵌入子目錄下你可以找到FillTable.java的源代碼。
import java.sql.*;
public class TableFiller {
Connection conn = null;
PreparedStatement insertCust
= null;
PreparedStatement insertOrder
= null;
上面的申明是標準的JDBC申明。conn控制JDBC連接。insertCust和insertOrder將分別處理插入記錄到custs和orders表里的SQL語句。PreparedStatement的使用使關系數據庫管理系統得到優化的可能。
其次,下面的代碼,driverName包含我們裝載和使用的JDBC驅動器的類名。這是一個嵌入式驅動器。連接的URL是url值。你可以看見是使用的絕對路徑定位這個數據庫(注意:你必須要使用正斜線來分離路徑)。如果你總是在你的工作目錄運行這個程序的話,你可以僅使用”jdbc:derby:vsjdb”。也可以可以設置derby.system.home屬性來改變Derby數據庫文件的位置(例如:java –D derby.system.home=c:\mydbdir org.apche.derby.tools.ij)。
String driverName =
"org.apache.derby.jdbc.EmbeddedDriver";
String url =
"jdbc:derby:c:/derby1021/vsjdb";
loadDrivers()方法裝載JDBC驅動類并創建獲得一個Derby的JDBC連接。并準備兩個插入語句。
public void loadDrivers()
throws SQLException,
ClassNotFoundException {
Class.forName(driverName);
conn = DriverManager.getConnection(
url);
insertCust = conn.prepareStatement(
"INSERT INTO custs VALUES(
?, ?)");
insertOrder =
conn.prepareStatement(
"INSERT INTO orders VALUES(
?, ?, ?)");
}
TableFiller的main()方法創建一個TableFiller的實例,并調用它的addCustomer()方法去創建1000個用戶。它也調用addOrder()方法去創建10000條定單信息。為了顯示進度,它打印顧客編號和’.’到系統輸出中。
public static void main(String args[])
throws Exception {
TableFiller tf = new TableFiller();
tf.loadDrivers();
int orderNum = 1;
for (int i=1; i<1001>
String custNum = "" + i;
tf.addCustomer(
custNum, "customer #" + i);
System.out.print("\n"
+ custNum);
for (int j=1; j<11>
tf.addOrder( ""+ orderNum,
custNum, j * 99);
orderNum++;
System.out.print(".");
}
}
tf.closeAll();
}
addCustomer()方法獲得參數并執行insertCust的預編譯語句。
public void addCustomer(
String id, String custname)
throws SQLException {
insertCust.setString(1, id);
insertCust.setString(2, custname);
insertCust.executeUpdate();
}
addOrder()方法獲得參數并執行insertOrder的預編譯語句。
public void addOrder(String id,
String custid, int total)
throws SQLException {
insertOrder.setString(1, id);
insertOrder.setString(2, custid);
insertOrder.setInt(3, total);
insertOrder.executeUpdate();
}
closeAll()整理和關閉兩個預編譯語句和JDBC連接,通知Derby釋放被控制的資源。
public void closeAll()
throws SQLException {
insertCust.close();
insertOrder.close();
conn.close();
}
}
當顧客和定單被創建,程序將打印顧客編號到屏幕上。編號從1到1000表明每個顧客被創建。而打印的每個’.’則表明定單被創建。
要編譯這個代碼,你僅僅需要確信你已經設置了classpath,并且使用標準的Java編譯命令:
java TableFiller.java
你要確保沒有ij或其他Derby會話在運行。在嵌入式模式你需要唯一的訪問數據庫。在編譯成功后,需要復制TableFiller.class文件到你的工作目錄下,然后從那里運行TableFiller:
java TableFiller
你應該看見打印出來的狀態和寫入數據庫的記錄。
檢驗被創建的記錄
現在,去看看你創建的顧客和定單信息,確保你在工作目錄并再次登錄到ij。連接vsjdb數據庫。
connect ‘jdbc:derby:vsjdb’;
然后使用下面的SELECT語句查看所有1000條顧客信息。
select * from custs;
同樣的使用下面的SELECT語句查看所有10000條定單信息。
select * from orders;
當然,使用類似于FillTable.java里的標準JDBC代碼,你可以整合Derby的關系數據庫的訪問功能到你的任何一個工程中。當你的項目需要一個嵌入式數據庫時,有能力簡單和快速處理產生大量的數據的Derby是你最好的選擇。Derby的自由Apache許可允許你綁定它到你的程序上,即使你決定把你的產品進行商業買賣。
探索Derby的高級特性
由于Derby是從IBM中分離出來的,Derby有許多高級功能——具有代表性的僅僅建立在高端的關系數據庫管理系統中。插圖3展現了幾個有趣的特性。
插圖3:Derby的數據庫特性
在插圖3中,該數據庫存儲包括數據表,圖表,關系信息——這是所有關系數據庫所必須有的。另外,你可以看見它也可以包含觸發器,存儲過程,甚至Java代碼。這些高級特性將在文章的后面部分探究。Derby的網絡模式的操作也將被提及。
配置Derby的網絡模式
要訪問Derby的網絡服務器模式,首先你需要把下面的JAR文件地址添加到你的classpath值里。
derby_installation_directory\lib\derbynet.jar
你還需要為客戶端訪問下載一個網絡JDBC驅動。如果你使用IBM DB2 JDBC普通驅動,你則需要把下面的JAR文件地址添加到你的classpath值里:
derby_installation_directory\lib\db2_jcc.jar
derby_installation_directory\lib\db2_jcc_license_c.jar
batch子目錄里的sp.bat文件里的classpath值已經包含了這些JARs文件地址。
啟動網絡服務器,使用下面的命令:
java org.apache.derby.drda.NetworkServerControl start
你也可以使用batch子目錄下的netsvr.bat文件。
在默認情況下,服務器將監聽TCP1527端口來接收客戶端請求。你可以使用”-p
”參數來改變端口。
如果你需要關閉服務器,使用下面的命令:
java org.apache.derby.drda.NetworkServerControl shutdown
或者你可以使用batch子目錄下的netstop.bat文件。
現在服務器已經準備好了,為我們下面的探究鋪上了臺階。