HSQLDB简介知识介绍
HSQLDB简介知识介绍
HSQLDB是一个纯Java的数据库,小巧方便,在做应用程序的demo时会带来很大的方便。我们可以从http://hsqldb.sourceforge.net/下载hsqldb,里面包括源代码,文档以及demo等等。hsqldb.jar包
这个包位于/lib目录下包括一些组件和程序,可以用不同的命令来启动这些程序。hsqldb.jar中的组件:
HSQLDB RDBMS HSQLDB JDBC Driver Database Manager (Swing and AWT versions) Transfer Tool (AWT version) Query Tool (AWT) Sql Tool (command line) |
其中,HSQLDB RDBMS和JDBC Driver提供了核心的功能,其它的都是一些通用的数据库工具,只要你有其它的驱动,这些工具可以同其他数据库一起工作。
运行工具
所有的工具都可以以jar方式运行,下面是简单的例子:
java -cp ../lib/hsqldb.jar org.hsqldb.util.DatabaseManager java -cp hsqldb.jar org.hsqldb.util.DatabaseManager |
Hsqldb工具的主类:
org.hsqldb.util.DatabaseManager org.hsqldb.util.DatabaseManagerSwing org.hsqldb.util.Transfer org.hsqldb.util.QueryTool org.hsqldb.util.SqlTool |
其中,如DatabaseManager和SqlTool都可以有命令行参数,你可以用-?来察看它们有什么参数。DatabaseManager和Transfer都有图形界面可以更好地交互。
运行Hsqldb
HSQLDB可以以不同的方式运行,一般将它们分为Server模式和In-Process模式。每一个HSQLDB数据库包含2到5个文件,它们有同样的名字和不同的后缀名,位于同一个目录中。举例来说,一个叫做test的数据库会包含以下的文件:
test.properties test.script test.log test.data test.backup |
properties文件包含数据库的一般配置。script文件包含表的定义,其他数据库对象,以及non-cached表的数据。log文件则包含数 据库最近的更新。data文件包含cached表的数据,backup文件则是上次持久化后的data文件的打包文件。这些文件都是有用的不能被删除。如 果数据库没有cached表,则.data和.backup文件是不会存在的。
当test数据库被操作的时候,test.log文件被用来纪录数据的修改。这个文件在数据库正常关闭时会被删除掉,否则(非正常关闭)这个文件 将会用来在下次启动时重新更新数据。一个test.lck文件用来纪录数据库是打开的。这个文件也会在正常关闭时删除。在某些情况下, test.data.old会被创建接着被删除。
注意:当引擎关闭数据库的时候,它将会创建以.new为后缀的临时文件,再将它们重命名为上述这些文件。
(二)
Server模式
Server模式提供了最大的可访问性。在这种模式下,数据库引擎运行在一个JVM中,并且监听同一台机器上或网络上其他机器上程序的连接。几个不同的程序可以连接到服务并且取得和更新信息。应用程序通过HSQLDB JDBC驱动连接数据库。
根据客户端和服务器通信的协议不同,Server模式可以分为以下三种:
Hsqldb Server:
这种模式是首选的并且是最快的。它使用hsqldb私有的通信协议。启动数据库的命令和上面的启动工具的命令差不多,以下就是一个例子,它将启动一个文件名为"mydb.*"的数据库服务。
java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 mydb -dbname.0 xdb |
-?可以用来察看可用的参数。
Hsqldb Web Server:
当只能通过HTTP协议访问数据库所在机器的时候,这种模式就可以被使用了。使用Web Server模式的唯一原因就是穿过客户端和服务器之间的防火墙,其他情况下最好不要使用。HSQLDB Web Server是一个特殊的web服务,允许JDBC客户端通过HTTP协议访问。从1.7.2版本开始,这种模式也开始支持事务。
运行这种模式的服务,只要将上面例子中的主类替换为:org.hsqldb.WebServer就可以了。
Hsqldb Servlet:
这种模式使用同Web Server同样的协议。在诸如Tomcat或Resin等servlet引擎提供数据库访问的时候,这种模式就可以使用了。Servlet模式不能脱离 了servlet引擎而单独运行。hsqldb.jar中的hsqlServlet类应该被放置在应用服务器中提供数据库连接。数据库通过应用服务的属性 指定,可以察看hsqlServlet.java获得更详细的信息。
Servlet模式只能提供一个数据库。
连接一个作为服务运行的数据库
一旦一个HSQLDB服务运行起来,客户端代就可以通过HSQLDB JDBC驱动来连接它。如何连接一个数据库服务在jdbcConnection的javadoc中有详细的说明。下面是一个普通的例子:
try { Class.forName("org.hsqldb.jdbcDriver" ); } catch (Exception e) { System.out.println("ERROR: failed to load HSQLDB JDBC driver."); e.printStackTrace(); return; } Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "sa", ""); |
在有些环境下,你需要用下面的语句来得到驱动:
Class.forName("org.hsqldb.jdbcDriver").newInstance(); |
注意,上面的URL中没有提及数据库的具体文件,因为它们是在启动时指定好的。
In-Process(Standalone)模式
这种模式将数据库引擎作为你应用程序的一部分运行在同一个JVM中。在一些程序中这种模式要快得多,因为数据不需要修改以及通过网络传输。主要的 缺点是不能从你的应用程序外部连接数据库了,这样的结果就是在应用程序运行的时候,你不能使用一个外部的工具来察看你数据库中的数据。在1.7.2版本 中,你可以在同一个JVM中开一个独立的线程来运行服务器实例,这样就可以从外部访问你的in-process数据库了。
建议在开发应用程序的时候使用HSQLDB服务器实例,而在部署的时候切换到In-Process模式。
一个In-Process模式的数据库是从JDBC语句启动的,把文件的路径作为URL的一部分。举例来说,如果数据库的名字叫作testdb,启动应用程序的命令(cmd)运行的目录和数据库文件的目录是同一个目录,下面的语句就是启动这个数据库并得到连接:
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:testdb", "sa", ""); |
数据库文件路径的分割符使用斜杠("/"),Windows和Linux都可以。所以相对路径或者同一个驱动器下的目录路径在两种操作系统上都是一样的。
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb", "sa", ""); |
当使用相对路径的时候,这些路径将会从启动JVM的目录开始计算,从jdbcConnection的Javadoc中获得更多的信息。
Memory-Only数据库
HSQLDB还可以运行在内存中,数据不持久化而是全部在内存中。因为没有任何信息写在磁盘上,所以这种模式只能用于处理应用数据,比如applet或其他的一些应用中。这种模式通过mem:协议来指定:
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:aname", "sa", ""); |
关闭数据库
任何模式的数据库都可以通过一个SQL命令:SHUTDOWN来关闭。在1.7.2版本中,当所有连接都被显式地关闭之后,in-process 模式的数据库还是不会被关闭,除非有SHUTDOWN命令。当SHUTDOWN命令发出,所有的active事务都会被rollback。
创建一个新的数据库
当一个数据库实例启动(也就是cmd命令执行时),或者创建一个in-process模式数据库连接的时候,如果指定的路径没有数据库存在,那么就会创建一个新的空的数据库。
所以如果你不想这种情况发生,你可以在增加一个connection属性ifexists=true来检查是否存在这样一个数据库,不存在的话就会抛出异常。
(三)
前面已经看到HSQLDB可以在同一个JVM中以服务的形式启动,我们可以在应用启动的时候,比如在app加载的时候,在listener中启动数据库,然后就可以使用数据库了,不需要再去专门启动数据库。
下面是我写的DatabaseThread以及测试代码,可以把启动的工作放到app加载的时候。
package rst.hsqldb.start;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.hsqldb.Server;
import junit.framework.TestCase;
/**
* Class description.
*
* @author rst
*/
public class TestStartServerInCode extends TestCase {
/*
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
DatabaseThread db = new DatabaseThread();
//mostly can add 10 database instance.
db.addDatabase("db/db");
new Thread(db).run();
//wait for finishing start.
Thread.sleep(5000);
}
/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
}
public void testStart() throws ClassNotFoundException, SQLException{
Class.forName("org.hsqldb.jdbcDriver");
Connection conn=DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/db;ifexists=true","sa","");
assertNotNull(conn);
conn.close();
}
}
class DatabaseThread implements Runnable {
private String address = "localhost";
private int port = 9001;
private boolean silent = true;
private boolean trace = true;
private List databases = new ArrayList();
public void addDatabase(String path){
databases.add(path);
}
/**
* @return Returns the address.
*/
public String getAddress() {
return address;
}
/**
* @param address The address to set.
*/
public void setAddress(String address) {
this.address = address;
}
/**
* @return Returns the databases.
*/
public List getDatabases() {
return databases;
}
/**
* @param databases The databases to set.
*/
public void setDatabases(List databases) {
this.databases = databases;
}
/**
* @return Returns the dbnames.
*/
public String[] getDbnames() {
return dbnames;
}
/**
* @param dbnames The dbnames to set.
*/
public void setDbnames(String[] dbnames) {
this.dbnames = dbnames;
}
/**
* @return Returns the port.
*/
public int getPort() {
return port;
}
/**
* @param port The port to set.
*/
public void setPort(int port) {
this.port = port;
}
/**
* @return Returns the silenct.
*/
public boolean isSilent() {
return silent;
}
/**
* @param silenct The silenct to set.
*/
public void setSilent(boolean silent) {
this.silent = silent;
}
/**
* @return Returns the trace.
*/
public boolean isTrace() {
return trace;
}
/**
* @param trace The trace to set.
*/
public void setTrace(boolean trace) {
this.trace = trace;
}
private String[] dbnames;
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
String[] args = null;
ArrayList list = new ArrayList();
if(address != null){
list.add("-address");
list.add(address);
}
if(port != 0){
list.add("-port");
list.add(""+port);
}
list.add("-silent");
list.add("" + silent);
list.add("-trace");
list.add("" + trace);
for(int i = 0; i < databases.size(); i++){
list.add("-database." + i);
list.add((String) databases.get(i));
list.add("-dbname." + i);
String database = (String) databases.get(i);
String dbname = database.substring(database.lastIndexOf("/")+1);
list.add(dbname);
}
//args = (String[]) list.toArray();
args = new String[list.size()];
for(int i = 0; i < list.size(); i++){
args = (String) list.get(i);
System.out.println(args);
}
//System.out.println(args);
//调用HSQLDB的服务入口
Server.main(args);
}
}
转之:http://rongsantang.yculblog.com/post.626267.html (一地鸡毛)
HSQL文档网址:http://hsqldb.sourceforge.net/web/hsqlDocsFrame.html