當前位置:首頁 > 嵌入式 > 嵌入式硬件
[導(dǎo)讀]嵌入式數(shù)據(jù)庫無需安裝,體積小巧,速度又很快,在很多場合可以替代目前流行的MySQL, SQLServer等大中型數(shù)據(jù)庫。本文介紹兩種嵌入式數(shù)據(jù)庫產(chǎn)品:Berkeley DB和SQLite,并著重討論它們與Java之間的接口。

嵌入式數(shù)據(jù)庫無需安裝,體積小巧,速度又很快,在很多場合可以替代目前流行的MySQL, SQLServer等大中型數(shù)據(jù)庫。本文介紹兩種嵌入式數(shù)據(jù)庫產(chǎn)品:Berkeley DB和SQLite,并著重討論它們與Java之間的接口。

通常我們采用各種數(shù)據(jù)庫產(chǎn)品來實現(xiàn)對數(shù)據(jù)的存儲、檢索等功能,例如,Oracle,SQL Server,MySQL等等。這些產(chǎn)品除提供基本的查詢,刪除,添加等功能外,也提供了很多高級特性,如觸發(fā)器,存儲過程,數(shù)據(jù)備份恢復(fù),全文檢索功能等。但實際上,很多的應(yīng)用,僅僅利用到了這些數(shù)據(jù)庫產(chǎn)品的基本特性而已。而且在一些小型應(yīng)用上,或者某些特殊場合的應(yīng)用,比如桌面程序,這些數(shù)據(jù)庫產(chǎn)品就明顯有一些臃腫。在這些情況下,嵌入式數(shù)據(jù)庫的優(yōu)勢就特別明顯了。

嵌入式數(shù)據(jù)庫無須獨立運行的數(shù)據(jù)庫引擎,它是由程序直接調(diào)用相應(yīng)的API去實現(xiàn)對數(shù)據(jù)的存取操作。更直白的講,嵌入式數(shù)據(jù)庫是一種具備了基本數(shù)據(jù)庫特性的數(shù)據(jù)文件。嵌入式數(shù)據(jù)庫與其它數(shù)據(jù)庫產(chǎn)品的區(qū)別是,前者是程序驅(qū)動式, 而后者是引擎響應(yīng)式。嵌入式數(shù)據(jù)庫的一個很重要的特點是它們的體積非常小,編譯后的產(chǎn)品也不過幾十K。這不但對桌面程序的數(shù)據(jù)存儲方案是一個很好的選擇,也使得它們可以應(yīng)用到一些移動設(shè)備上。同時,很多嵌入式數(shù)據(jù)庫在性能上也優(yōu)于其它數(shù)據(jù)庫,所以在高性能的應(yīng)用上也常見嵌入式數(shù)據(jù)庫的身影。

下面介紹的是兩個開放源代碼的嵌入式數(shù)據(jù)庫,Berkeley DB和SQLite。同時側(cè)重介紹如何應(yīng)用Java連接這兩種嵌入式數(shù)據(jù)庫。

一. Berkeley DB

1. 簡介

Berkeley DB是一款健壯的,高速的工業(yè)級嵌入式數(shù)據(jù)庫產(chǎn)品,你可以在它的官方主頁(見參考鏈接一)上發(fā)現(xiàn)很多知名的公司都采用了這款嵌入式數(shù)據(jù)庫。Berkeley DB的一個很重要的特點是就是高速存儲。在高流量,高并發(fā)的情況下,Berkeley DB要比非嵌入式的數(shù)據(jù)庫表現(xiàn)得更加出色。所以在一些技術(shù)實現(xiàn)上,Berkeley DB被作為大型關(guān)系數(shù)據(jù)庫的中間數(shù)據(jù)緩沖層,用來快速的保存數(shù)據(jù),可能會在適當?shù)臅r刻再導(dǎo)入到大型數(shù)據(jù)庫中,進而應(yīng)用大型數(shù)據(jù)庫所提供的更為高級的特性。

Berkeley DB雖然是開源的產(chǎn)品,但對某些條件下的商業(yè)性應(yīng)用,卻不是免費的,而且價格頗為昂貴。這些商業(yè)條件排除了開源的情況,不發(fā)放分布版本的情況,等等。比如,如果你的程序是開放源代碼的或者僅僅應(yīng)用到單一的網(wǎng)站上,在這種情況下,Berkeley DB是免費的。

2. 獲得Java與Berkeley DB的接口

Berkeley DB目前的版本是4.1.25,自帶了Java接口。下載的壓縮包中包含C和Java語言的源代碼和編譯配置文件。在Windows平臺,可以用MS Visual C++ 6.0或MS VC.Net編譯。用VC6編譯的操作如下介紹:在源代碼的build_win32路徑下打開VC的工程文件,之后在Build菜單中的Set Active Configuration選擇db_java win32 release編譯選項。在VC的Tools菜單Options選項中指定JNI.H等Java本地化接口編譯時所需要頭文件的位置。你會在JDK的include路徑下找到這些頭文件, 例如加入的路徑可能會是這樣的:C:jdk1.4include和C:jdk1.4includewin32。最后在Tools菜單中Options選項還要設(shè)置Javac.exe和Jar.exe的執(zhí)行路徑,這個設(shè)置會使VC開發(fā)環(huán)境也能調(diào)用Java編譯器,從而在VC環(huán)境下直接完成對Java接口類的編譯和打包。在編譯后,在release 路徑下的文件中找到db.jar, libdb41.dll, libdb_java41.dll,這三個文件組成了Berkeley DB 的Java接口程序包。

3. 應(yīng)用Java與Berkeley DB的接口

Berkeley DB并不是一個關(guān)系型的數(shù)據(jù)庫。不能應(yīng)用標準的SQL語句對數(shù)據(jù)庫操作,對它的操作要調(diào)用專用的API實現(xiàn)。這些API提供了查詢、插入、刪除等功能。比如com.sleepycat.db.Db類代表數(shù)據(jù)庫對象。Db類的put()方法完成的是插入功能,get()方法完成的是讀出數(shù)據(jù)的功能。

Berkeley DB每一個記錄都有一個鍵值和對應(yīng)的數(shù)據(jù)值,而鍵值和數(shù)據(jù)必須是類com.sleepycat.db.Dbt的對象或其子類的對象。Dbt提供了一些方法可以將byte數(shù)組或Object對象保存到Dbt的對象中去。比如,Dbt類中的set_data(byte[])或set_object(Object)方法。注意到目前Berkeley DB中的Java API命名方法并不符合Java的命名規(guī)范,比如set_data()方法應(yīng)該命名為setData()方法。Berkeley DB許諾在下一個版本中會提供符合命名規(guī)范的Java API。

Berkeley DB對任何存入的數(shù)據(jù)都是直接原樣存儲到數(shù)據(jù)文件中去,無論其是二進制數(shù)據(jù)還是ASCII或Unicode等編碼的文本。通??梢岳眠@一特性和Java串行化的概念方便的進行數(shù)據(jù)的存取。例如聲明一個類
public class AccountInfo implements Serializable{
//帳戶信息
public String loginName;
public String password;
public boolean auotLogin;
}

在這個AccountInfo類中僅僅包含了數(shù)據(jù)項的定義。我們完全可以將這個類看作數(shù)據(jù)庫的表中字段定義??梢杂肂erkeley DB保存AccountInfo對象的串行化二進制數(shù)據(jù),以此來保存這個對象中的變量值。在操作中,先對Dbt的對象調(diào)用set_object(AccountInfo)方法,而后把這個Dbt對象作為一條紀錄保存到表中。當然,我們也可以應(yīng)用繼承Dbt類的方法來完成對數(shù)據(jù)的保存。

下面這段簡單代碼演示如何將數(shù)據(jù)存入到數(shù)據(jù)庫中,然后再用游標對象瀏覽全部數(shù)據(jù)。

//注意,下面的程序的忽略了對異常處理,寫入數(shù)據(jù)初始化等等一些代碼,請在適當修改后再編
//譯運行它
Db dbFile = null;
//生成Db對象
dbFile = new Db(null, 0);
//用BTree方式打開數(shù)據(jù)庫,庫文件是在c:/temp下的mydata.db文件,表名是employee
//如果數(shù)據(jù)庫不存在,則自動生成一個新的數(shù)據(jù)庫。
dbFile.open(null,"c:\temp\mydata.db","employee",Db.DB_BTREE,
Db.DB_CREATE,0);
Dbt key = new Dbt();
Dbt data = new Dbt();
//向庫文件中插入一條數(shù)據(jù),如果已經(jīng)存在,打印出錯信息
if (dbFile.put(null,key, data, Db.DB_APPEND) == Db.DB_KEYEXIST) {
System.out.println("Key already exists.");
}
//關(guān)閉數(shù)據(jù)文件
dbFile.close(0);
//重新打開數(shù)據(jù)文件
dbFile = new Db(null, 0);
dbFile.open(null, "c:\temp\mydata.db", "employee", Db.DB_UNKNOWN, 0, 0644);
// 聲明一個數(shù)據(jù)庫游標Dbc對象iterator
Dbc iterator = dbFile.cursor(null, 0);
// 遍歷整個表
Dbt key = new Dbt();
while (iterator.get(key, data, Db.DB_NEXT) == 0)
{
System.out.println("reading");
}

//關(guān)閉游標和數(shù)據(jù)文件
iterator.close();
dbFile.close(0);

在運行Berkeley DB的程序時勿必在系統(tǒng)環(huán)境變量PATH中設(shè)置libdb41.dll和 libdb_java41.dll所在的路徑。

4. Berkeley DB的存儲模式

Berkeley DB提供了四種存儲數(shù)據(jù)的模式:Btree,Hash,Queue和Recno。在打開數(shù)據(jù)庫的時候要指定一種存儲模式,比如上例中open()方法中的參數(shù)Db.DB_BTREE就是指定以Btree模式打開數(shù)據(jù)庫。

Btree模式是以排序的二叉樹的方式存儲,Hash是以線性哈希表的方式存儲。Queue用邏輯記錄號做為鍵值,以定長的數(shù)據(jù)為記錄值。Recno方式也以邏輯記錄號做為鍵值,但可以保存定長或變長的記錄值。這里提到的邏輯記錄號有兩種,可變的和固定的??勺冞壿嬘涗浱枙鶕?jù)數(shù)據(jù)記錄的增加與刪除做相應(yīng)的變化。比如在數(shù)據(jù)庫中共有100條記錄,如果刪除第80條記錄,那么第81條記錄的邏輯記錄號會自動變成80,以此類推,第100條記錄邏輯記錄號會變成99。固定的邏輯記錄號則無論數(shù)據(jù)庫如何操作都不會有變化。Queue模式下,邏輯記錄號只能是固定方式。

Recno模式則可通過配置來選擇是采用那種類型的記錄號作為鍵值。Btree模式也可以通過設(shè)置,將可變的邏輯記錄號做為鍵值。

這幾種存儲模式各有優(yōu)缺點,要根據(jù)具體的需求來選擇。當鍵值不想用邏輯記錄號時Btree或Hash是必須的選擇。Btree方式比較適合連續(xù)的順序讀取,比如,當鍵值是時間值,如果經(jīng)常有從某一時間點開始連續(xù)讀取后繼的記錄的操作,Btree是一種很好的選擇。對隨機的跳躍式讀取,Hash模式則更為恰當。Queue和Recno都以記錄號為鍵值,但前者適合先進先出的讀取方式。

Recno則通常是存取變長文本記錄的理想存儲模式。

5. Berkeley DB Environment的概念

Berkeley DB Environment為一組數(shù)據(jù)庫同時提供參數(shù)設(shè)置。更為重要的是,如果要應(yīng)用更高級的特性,必須要使用Environment功能,比如在想要對保存的數(shù)據(jù)進行加密存儲時。

6. 更多特點

除了最基本的插入、查詢、刪除功能以外,Berkeley DB還提供了一些特性,比如Transaction,數(shù)據(jù)加密,同步加鎖控制,錯誤日志等功能。下面的圖片是Berkeley DB功能示意圖。

二. SQLite

1. 簡介

相信PHP的開發(fā)人員一定不會對SQLite感到陌生,因為在PHP5中已經(jīng)集成了這個輕巧的內(nèi)嵌式數(shù)據(jù)庫產(chǎn)品。SQLite與Berkeley DB相比,在操作語句上更類似關(guān)系型數(shù)據(jù)庫的產(chǎn)品。絕大多數(shù)標準的SQL92語句SQLite都能支持。

SQLite的版權(quán)允許無任何限制的應(yīng)用,包括商業(yè)性的產(chǎn)品。在參考鏈接二上提供的SQLite官方主站上可以下載到編譯后的SQLite程序。但推薦應(yīng)用CVS工具下載最新版本的SQLite源代碼。如果在*nux平臺下,可直接用make編譯。如果在Windows平臺,常用的有兩種方法,

一是應(yīng)用在Windows平臺下的Linux仿真程序,如MingW或Cygwin提供的make來編譯。

二是應(yīng)用MS VC平臺編譯。后者設(shè)置略有麻煩,但可仿照參考鏈接五上提供的MS VC6工程文件的樣例。應(yīng)用到這個樣例的時候,要注意的是由于SQLite源代碼在不斷更新,如果直接應(yīng)用樣例所提供的VC6工程文件編譯會出現(xiàn)一些問題,讀者要根據(jù)具體的情況稍微調(diào)整一下編譯的設(shè)置。

2. 編譯第三方Java接口

SQLite源代碼是C,而且官方網(wǎng)站上只提供了C和Tcl語言的接口。為了應(yīng)用Java接口,要采用第三方的接口驅(qū)程,可在參考鏈接三中找到這個Java接口程序。這個接口提供了兩種連接SQLite 的方式:一是直接用JNI技術(shù)調(diào)用SQLite的C語言接口,這種方式要求開發(fā)人員要對SQLite本身的API也有一定的了解。在第二種方式中,接口程序?qū)崿F(xiàn)了Java標準規(guī)范的JDBC接口,這樣開發(fā)人員只要對JDBC有了解就可以了。

下面介紹在Windows系統(tǒng)MS VC6環(huán)境中編譯SQLite Java接口(同時包括JNI和JDBC兩個接口)的過程。如果你對C語言編譯的設(shè)置很熟悉,可以跳這這段介紹。

第一步先把SQLite源代碼編譯成Lib靜態(tài)庫文件。具體的步驟可以直接應(yīng)用下面參考鏈接中提供的MS VC6工作區(qū)文件,其中有一個編譯SQLite到靜態(tài)庫的設(shè)置。編譯成功后得到SQLite.lib文件。
第二步要建立一個新的VC DLL項目,然后和上面介紹的Berkeley DB在編譯Java本地化接口的設(shè)置一樣,在VC的Tools菜單Options選項中指定JNI.H等JNI編譯所要的頭文件位置。同時還要指定sqlite.h頭文件位置,這個文件是在生成SQLite靜態(tài)庫的時候自動生成的,可以在SQLite.lib文件所在的工作區(qū)目錄下面找到它,例如加入的路徑為C:sqlitemsvc6。然后在Project菜單的setting選項設(shè)置Link到SQLite.lib庫文件,并再次在Tools菜單中Options指定SQLite.lib的查找路徑。注意有些情況下可能要設(shè)置予編譯選項HAVE_SQLITE_COMPILE以便使用SQLite中VM的一些功能。編譯成功后可得到Sqlite_jni.dll文件。

第三方接口庫中的Java代碼包含JNI接口和多個版本的JDBC接口程序,可根據(jù)你的JRE的版本選擇相應(yīng)的JDBC程序。編譯這些Java代碼的過程這里就不做敘述了。

編譯后的Java類包加上前面得到的Sqlite_jni.dll文件,組成了SQLite的Java接口庫,在應(yīng)用Java語言調(diào)用JDBC或JNI接口時,都是通過應(yīng)用Java的本地化技術(shù)調(diào)用Sqlite_jni.dll文件,完成對SQLite數(shù)據(jù)庫的操作。

3. 應(yīng)用JNI直接調(diào)用SQLite功能

下面這段代碼演示如何應(yīng)用JNI接口操作SQLite??梢钥吹紻atabase類的exec()方法是執(zhí)行SQL語句的關(guān)鍵:

Database db = new Database();
try {
//打開數(shù)據(jù)庫
db.open("c:\temp\mydata.slt", 0666);
db.interrupt();
db.busy_timeout(1000);
db.busy_handler(null);
db.exec("create table account (name varchar(10),gale boolean)",result);
db.exec("insert into account values('steve','m')", result);
db.exec("select * from account",result);
//關(guān)閉數(shù)據(jù)庫
db.close();
} catch (Exception e) {
e.printStackTrace();
}

4. 應(yīng)用JDBC連接SQLite

用"SQLite.JDBCDriver"作為JDBC的驅(qū)動程序類名。連接JDBC的URL格式為jdbc:sqlite:/path。這里的path為指定到SQLite數(shù)據(jù)庫文件的路徑,例如:

jdbc:sqlite://dirA/dirB/dbfile
jdbc:sqlite://DRIVE:/dirA/dirB/dbfile
jdbc:sqlite://COMPUTERNAME/shareA/dirB/dbfile

參考下面的應(yīng)用JDBC連接SQLite的例程:

//聲明JDBC驅(qū)動程序
Class clz = Class.forName("SQLite.JDBCDriver");
//連接數(shù)據(jù)庫
Connection conn = DriverManager.getConnection("jdbc:sqlite:/c:/temp/e2.db");
Statement stmt = conn.createStatement();
//生成person表,包含名子和年齡字段
stmt.execute("create table person (name varchar(100),age int)");
//插入數(shù)據(jù)
stmt.execute("insert into person values('steve',25)");
//用SQL語句讀出數(shù)據(jù)
result = stmt.executeQuery("select * from person");
while(result.next()){
System.out.println(result.getString(1));
System.out.println(result.getInt(2));
}

運行程序時要在Java.exe命令行加入選項java.library.path指定到Sqlite_jni.dll所在的路徑。例如,如果Sqlite_jni.dll放在c:sqliteNative 路徑下面,運行類com.e2one.MyClass 的命令行將會是這樣:java -Djava.library.path=c:sqliteNative com.e2one.MyClass。

5. SQLite的特點

SQLite是無數(shù)據(jù)類型的數(shù)據(jù)庫。雖然在生成表結(jié)構(gòu)的時候,要聲明每個域的數(shù)據(jù)類型,但SQLite并不做任何檢查。開發(fā)人員要靠自己的程序控制輸入與讀出數(shù)據(jù)的類型是正確的。這里有一個例外,就是當主鍵為整型值時,如果要插入一個非整型值時會產(chǎn)生異常。另外,雖然在插入或讀出數(shù)據(jù)的時候是不區(qū)分類型的,但在比較的時候,不同數(shù)據(jù)類型是有區(qū)別的。比如:

CREATE TABLE MyTable(a INTEGER, b TEXT);
INSERT INTO MyTable valueS(0,0);

當執(zhí)行下面的查詢:

SELECT count(*) FROM MyTable WHERE a=='00';

會返回一條記錄,因為字段a的類型是整型,而數(shù)字00與0是相等的。

而執(zhí)行下面的查詢則不會返回記錄:

SELECT count(*) FROM MyTable WHERE b=='00';

因為字段b是字符類型,字符"00"與"0"是不相等的。

SQLite提供了對Transaction的支持。應(yīng)用Transaction即保證了數(shù)據(jù)的完整性,也會提高運行速度,因為多條語句一起提交給數(shù)據(jù)庫的速度會比一條一條的提交方式更快。

對二進制數(shù)據(jù),SQLite不能直接保存。但可以先將二進制的數(shù)據(jù)轉(zhuǎn)換成ASCII編碼,然后再保存。Base64編碼機制是最常見的把二進制數(shù)據(jù)轉(zhuǎn)換成ASCII編碼的手段。在SQLite的C語言代碼encode.c中提供了Base64編碼的功能。對Java而言,在參考鏈接六中提供的Apache的XML RPC項目中可以找到一個Base64編碼的例子。

上面介紹了兩個比較常見的嵌入式數(shù)據(jù)庫,Berkeley DB速度極快,可靠性高,但學(xué)習(xí)起來有一定難度。SQLite則簡單易用,速度也很快,又可以應(yīng)用標準的JDBC連接,但它功能卻照Berkeley略有遜色,比如加密功能、二進制數(shù)據(jù)的處理等。



本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉