IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Java technology  >

在应用程序中嵌入数据库功能

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

刘冬 (winter.lau@163.com), 一直使用J2EE从事移动业务方面的开发

2003 年 10 月 28 日

本文中,作者向大家介绍了一种轻量级得关系数据库系统,它可以在建立应用系统的演示版时代替大型数据库系统的功能,使应用系统的演示版更加轻便。

有这个必要吗?

我相信很多人看到这个题目都会提出这样一个问题:为什么要嵌入数据库到应用程序中,有这个必要吗?是的,数据库的出现就是为了将应用逻辑以及数据存储逻辑分开,如果把二者又揉合在一起岂不是违背了这样一个初衷?但是设想一下这样一个情况:当我们发布一个应用程序时我们希望用户可以非常简单的把它运行起来,因为有时候是用户第一次试用你的产品并由此来决定是否采用这个产品的时候,第一感觉对用户来讲是非常重要。如果只是为了大概了解一下应用程序而需要做一大堆的前期工作,比如数据库的安装、配置、初始化,如果这并不是一个非常复杂的应用,那我想这么大的一堆设置工作对谁来说都是残酷的,给用户的第一次印象那么差,你还敢肯定他还会对这个产品感兴趣吗?

举个例子:现在网上有很多开放源码的门户平台软件,可谓是琳琅满目。当我们需要选择其中一个的时候,我想你肯定没有那么多时间对每个软件都一一进行深入了解,那么是什么因素决定最后选型的结果呢?在一开始你应该不会注意到每个门户软件的所有功能,你第一步要做的肯定是先把它运行起来感觉一下,如果你花了半天时间发现还没有按照安装手册配置起来的时候,就算功能再强大你也肯定失望透顶,而且这完全不是你能力的问题,这个软件真的糟透了。还是这个例子,我会选择Jetspeed,它安装够简单,因为它内嵌了一个数据库,我们无需在这方面花费额外的时间。当然考虑到性能的问题你同样可以使用其他独立的数据库产品,但是你在一开始会重视性能这个问题吗?





回页首


HSQLDB数据库是否支持标准SQL

如果你还能撑到这里或许可以说明你同意我刚才的观点,那么我们开始吧。

用来嵌入到应用程序的数据库引擎你肯定不会去关注它的性能怎么样?你更关心它是否够强大,是否支持标准的SQL语句以及是否有符合JDBC规范的驱动程序。这两个条件也就足够了,你还能要求什么呢?

HSQLDB支持的标准和特征:
1. 开放源码的数据库引擎
2. 使用标准SQL语法以及提供了JDBC驱动程序
3. 免费的数据库引擎
4. 是一个紧凑且快速的引擎
5. 可以独立运行或者嵌入到应用程序中
6. 设置可以在applet中使用
7. 可以自动建立索引以及使用索引
8. 支持数据库事务操作
9. 允许表间联合查询
10. 支持引用完整性检查
11. 支持JAVA的存储过程以及函数
12. 可以通过SQL脚本来创建数据库
13. 使用用户名和口令来控制访问权限
14. 兼容JDK1.1以及以上版本

这里罗列了HSQLDB最重要的一些特征,我们更关心的前几条。已经有很多产品使用了该数据库引擎,有如我们最开始举例的jetspeed,同时在sourceforge.net网站上很多关于内容管理的软件同样也使用了这个数据库引擎。我们完全可以放心将它植入到我们的应用程序中。由于HSQLDB本身支持标准SQL语法以及JDBC规范,因为我们可以很方便的移植到其他的数据库。





回页首


HSQLDB的数据存储结构

了解HSQLDB的数据存储结构可以更有利于我们对这个的集成。我们需要保证它不会跟我们的程序本身冲突,这也是最最基本的要求。

HSQLDB提供两种操作模式,进程内以及客户机服务器模式。由于我们的目的是为了嵌入因此我们只介绍进程内模式。应用该模式时数据库的访问只能是同一个虚拟机内。数据库的访问同样是使用JDBC接口,但又无需网络连接。运行于进程内模式的HSQLDB只能有一个数据库,也就是说我们无法同时创建两个或者两个以上的数据库并访问它们。

由于HSQLDB是完全运行内存中的数据库引擎,一旦数据库有改变时,这些信息会保存到磁盘中,以便下次启动的时候是最新的状态。由于是运行于内存中,所以数据量的大小就仅仅是受限于内存的大小。由于HSQLDB并不会应用在生产环境中,因此这个倒不是我们非常关心的问题。

启动一个HSQLDB实例的时候需要给它制定一个目录用于存放数据库的一些文件,这些文件包括$DBNAME.data,$DBNAME.properties,$DBNAME.script(其中$DBNAME为数据库名)这三个文件分别是数据文件;配置文件以及数据库创建的脚本文件,但是实际上数据文件内容是空的,所有的数据都写在脚本文件中。





回页首


开始嵌入HSQLDB数据库引擎

为了测试HSQLDB我们需要两个类,一个是数据库的服务线程,另外一个则是测试入口类,这两个类代码如下:

package lius.demo.hsqldb;
/* 
 * Created on 2003-10-5 by Liudong 
 * /
import java.io.*;
import java.sql.*;
import org.hsqldb.*;
/** 
 * HSQLDB数据库引擎测试类 
 * @author Liudong 
 */
 
public class HsqldbDemo {
  //数据库名称
  public final static String DATABASE_NAME = "hsqltest";
  //数据库端口缺省为9001	
  public final static int PORT = 9001;
	
  /**	 
   * 测试程序入口	 
   * @param args	 
   * @throws Exception	 
   */
   
  public static void main(String[] args) throws Exception {
    String path = "data";
    File f = new File(path);
    if(!f.exists())
      f.mkdirs();
    HsqlDBManager hsqldb = new HsqlDBManager(path);
    hsqldb.setDatabaseName(DATABASE_NAME);
    hsqldb.setPort(PORT);
    new Thread(hsqldb).start();
    System.out.println("数据库服务已启动");
		
    //开始测试
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    String sql = null;
    try{
      //连接数据库
      Class.forName("org.hsqldb.jdbcDriver");
      conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost","sa","");
      //创建表
      sql = "CREATE TABLE USER(ID INTEGER,NAME VARCHAR(50),MOBILE CHAR(12))";
      ps = conn.prepareStatement(sql);
      ps.executeUpdate();
      //插入数据
      sql = "INSERT INTO user VALUES(?,?,?)";
      ps = conn.prepareStatement(sql);
      ps.setInt(1, 1);
      ps.setString(2, "Winter Lau");
      ps.setString(3,"13912345678");
      ps.executeUpdate();
      //查询数据	
      ps = conn.prepareStatement("SELECT * FROM user");
      rs = ps.executeQuery();
      while(rs.next()){
        System.out.println("ID:"+rs.getInt("id"));
        System.out.println("NAME:"+rs.getString("name"));
	System.out.println("MOBILE:"+rs.getString("mobile"));
      }
    }
    finally{
      if(rs!=null)
        rs.close();
      if(ps!=null)
        ps.close();
      if(conn!=null)
        conn.close();
    }
		
    //退出程序
    System.exit(0);
  }
}
/** 
 * 数据库服务线程 
 * @author Liudong 
 */
class HsqlDBManager implements Runnable {
  String dataPath;
  String databaseName = "test";
  int port = -1;
  
  /**	 
   * 构造函数,需要一个数据路径的参数	 
   * 该参数必须为物理存在的路径	 
   * @param dataPath	 
   */
 
  public HsqlDBManager(String dataPath) {	
    this.dataPath = dataPath;
    if(!this.dataPath.endsWith(File.separator))
      this.dataPath += File.separator;
    this.dataPath += databaseName;
  }
  /
   * 线程入口	 
   * @see java.lang.Runnable#run()	 
   */
 
  public void run() {
    String[] args = null;
    if(port!=-1)
      args = new String[]{"-database",dataPath,"-port",port+""};
    else
      args = new String[]{"-database",dataPath};
  
    //调用HSQLDB的服务入口
    Server.main(args);
  }
	
  public String getDatabaseName() {
    return databaseName;
  }
  public String getDataPath() {
    return dataPath;
  }
	
  public void setDatabaseName(String string) {	
    databaseName = string;
  }
	
  public void setDataPath(String string) {
    dataPath = string;
  }
	
  public int getPort() {
    return port;
  }
	
  public void setPort(int i) {	
    port = i;
  }
}

运行该程序需要一个hsqldb.jar的包文件,其运行结果如下所示

数据库服务已启动
server.properties not found, using command line or default properties
Opening database: data\\test
HSQLDB server 1.7.1 is running
Use SHUTDOWN to close normally. Use [Ctrl]+[C] to abort abruptly
Tue Oct 14 10:34:52 CST 2003 Listening for connections ...
ID:1
NAME:Winter Lau
MOBILE:13912345678

由于同一个HSQLDB实例只能有一个数据库,所以我们在程序中的JDBC URL中并无需制定数据库名。通过上面的代码我们发现作为客户端在使用HSQLDB提供的数据库服务跟其他的商业数据库并没有什么区别,也就是说HSQLDB提供了基本的数据库功能,包括一些数据类型都非常完善。但是还是那句话,如果你不想惹麻烦的话请不要将HSQLDB用于生产环境,仅仅把它当成一个过渡环境只是为了方便开发一些DEMO程序用。



参考资料

HSQLDB网址 http://hsqldb.sourceforge.net/



关于作者

刘冬,一直使用J2EE从事移动业务方面的开发。你可以通过 winter.lau@163.com来联系他!




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

建议?







回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款