public class AccountInfo implements Serializable{
//帐户信息
public String loginName;
public String password;
public boolean auotLogin;
在这个AccountInfo类中仅仅包含了数据项的定义。我们完全可以将这个类看作数据库的表中字段定义。可以用Berkeley
DB保存AccountInfo对象的串行化二进制数据,以此来保存这个对象中的变量值。在操作中,先对Dbt的对象调用set_object
(AccountInfo)方法,而后把这个Dbt对象作为一条纪录保存到表中。当然,我们也可以应用继承Dbt类的方法来完成对数据的保存。
下面这段简单代码演示如何将数据存入到数据库中,然后再用游标对象浏览全部数据。
//注意,下面的程序的忽略了对异常处理,写入数据初始化等等一些代码,请在适当修改后再编
//译运行它
Db dbFile = null;
//生成Db对象
dbFile = new Db(null, 0);
//用BTree方式打开数据库,库文件是在c:/temp下的mydata.db文件,表名是employee
//如果数据库不存在,则自动生成一个新的数据库。
dbFile.open(null,"c:tempmydata.db","employee",Db.DB_BTREE,
Db.DB_CREATE,0);
Dbt key = new Dbt();
Dbt data = new Dbt();
//向库文件中插入一条数据,如果已经存在,打印出错信息
if (dbFile.put(null,key, data, Db.DB_APPEND) == Db.DB_KEYEXIST) {
System.out.println("Key already exists.");
}
//关闭数据文件
dbFile.close(0);
//重新打开数据文件
dbFile = new Db(null, 0);
dbFile.open(null, "c:tempmydata.db", "employee", Db.DB_UNKNOWN,
0, 0644);
// 声明一个数据库游标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");
}
//关闭游标和数据文件
iterator.close();
dbFile.close(0);
4. Berkeley DB的存储模式
Berkeley DB提供了四种存储数据的模式:Btree,Hash,Queue和Recno。在打开数据库的时候要指定一种存储模式,比如上例中open()方法中的参数Db.DB_BTREE就是指定以Btree模式打开数据库。
Btree模式是以排序的二叉树的方式存储,Hash是以线性哈希表的方式存储。Queue用逻辑记录号做为键值,以定长的数据为记录值。
Recno方式也以逻辑记录号做为键值,但可以保存定长或变长的记录值。这里提到的逻辑记录号有两种,可变的和固定的。可变逻辑记录号会根据数据记录的增
加与删除做相应的变化。比如在数据库中共有100条记录,如果删除第80条记录,那么第81条记录的逻辑记录号会自动变成80,以此类推,第100条记录
逻辑记录号会变成99。固定的逻辑记录号则无论数据库如何操作都不会有变化。Queue模式下,逻辑记录号只能是固定方式。Recno模式则可通过配置来
选择是采用那种类型的记录号作为键值。Btree模式也可以通过设置,将可变的逻辑记录号做为键值。
这几种存储模式各有优缺点,要根据具体的需求来选择。当键值不想用逻辑记录号时Btree或Hash是必须的选择。Btree方式比较适合连续的顺序读
取,比如,当键值是时间值,如果经常有从某一时间点开始连续读取后继的记录的操作,Btree是一种很好的选择。对随机的跳跃式读取,Hash模式则更为
恰当。Queue和Recno都以记录号为键值,但前者适合先进先出的读取方式。Recno则通常是存取变长文本记录的理想存储模式。
二. SQLite
1. 简介
相信PHP的开发人员一定不会对SQLite感到陌生,因为在PHP5中已经集成了这个轻巧的内嵌式数据库产品。SQLite与Berkeley DB相比,在操作语句上更类似关系型数据库的产品。绝大多数标准的SQL92语句SQLite都能支持。
SQLite的版权允许无任何限制的应用,包括商业性的产品。在参考链接二上提供的SQLite官方主站上可以下载到编译后的SQLite程序。但推荐应
用CVS工具下载最新版本的SQLite源代码。如果在*nux平台下,可直接用make编译。如果在Windows平台,常用的有两种方法,一是应用在
Windows平台下的Linux仿真程序,如MingW或Cygwin提供的make来编译。二是应用MS
VC平台编译。后者设置略有麻烦,但可仿照参考链接五上提供的MS
VC6工程文件的样例。应用到这个样例的时候,要注意的是由于SQLite源代码在不断更新,如果直接应用样例所提供的VC6工程文件编译会出现一些问
题,读者要根据具体的情况稍微调整一下编译的设置。
2. 编译第三方Java接口
SQLite源代码是C,而且官方网站上只提供了C和Tcl语言的接口。为了应用Java接口,要采用第三方的接口驱程,可在参考链接三中找到这个
Java接口程序。这个接口提供了两种连接SQLite的方式:一是直接用JNI技术调用SQLite的C语言接口,这种方式要求开发人员要对
SQLite本身的API也有一定的了解。在第二种方式中,接口程序实现了Java标准规范的JDBC接口,这样开发人员只要对JDBC有了解就可以
了。
下面介绍在Windows系统MS VC6环境中编译SQLite Java接口(同时包括JNI和JDBC两个接口)的过程。如果你对C语言编译的设置很熟悉,可以跳这这段介绍。
第一步先把SQLite源代码编译成Lib静态库文件。具体的步骤可以直接应用下面参考链接中提供的MS
VC6工作区文件,其中有一个编译SQLite到静态库的设置。编译成功后得到SQLite.lib文件。第二步要建立一个新的VC
DLL项目,然后和上面介绍的Berkeley
DB在编译Java本地化接口的设置一样,在VC的Tools菜单Options选项中指定JNI.H等JNI编译所要的头文件位置。同时还要指定
sqlite.h头文件位置,这个文件是在生成SQLite静态库的时候自动生成的,可以在SQLite.lib文件所在的工作区目录下面找到它,例如加
入的路径为C:sqlitemsvc6。然后在Project菜单的setting选项设置Link到SQLite.lib库文件,并再次在
Tools菜单中Options指定SQLite.lib的查找路径。注意有些情况下可能要设置予编译选项HAVE_SQLITE_COMPILE以便使
用SQLite中VM的一些功能。编译成功后可得到Sqlite_jni.dll文件。
第三方接口库中的Java代码包含JNI接口和多个版本的JDBC接口程序,可根据你的JRE的版本选择相应的JDBC程序。编译这些Java代码的过程这里就不做叙述了。
编译后的Java类包加上前面得到的Sqlite_jni.dll文件,组成了SQLite的Java接口库,在应用Java语言调用JDBC或JNI接
口时,都是通过应用Java的本地化技术调用Sqlite_jni.dll文件,完成对SQLite数据库的操作。
Database db = new Database();
try {
//打开数据库
db.open("c:tempmydata.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);
//关闭数据库
db.close();
} catch (Exception e) {
e.printStackTrace();
}
4. 应用JDBC连接SQLite
用"SQLite.JDBCDriver"作为JDBC的驱动程序类名。连接JDBC的URL格式为jdbc:sqlite:/path。这里的path为指定到SQLite数据库文件的路径,例如:
jdbc:sqlite://dirA/dirB/dbfile
jdbc:sqlite://DRIVE:/dirA/dirB/dbfile
jdbc:sqlite://COMPUTERNAME/shareA/dirB/dbfile
参考下面的应用JDBC连接SQLite的例程:
//声明JDBC驱动程序
Class clz = Class.forName("SQLite.JDBCDriver");
//连接数据库
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)");
//插入数据
stmt.execute("insert into person values('steve',25)");
//用SQL语句读出数据
result = stmt.executeQuery("select * from person");
while(result.next()){
System.out.println(result.getString(1));
System.out.println(result.getInt(2));
}
CREATE TABLE MyTable(a INTEGER, b TEXT);
INSERT INTO MyTable VALUES(0,0);
SELECT count(*) FROM MyTable WHERE a=='00';
SELECT count(*) FROM MyTable WHERE b=='00';