HsqlDb的持续化构建

在开发程序过程中,自从无意中使用了HsqlDb后,由于其速度特快,爱不释手(“不用不知道,谁用谁知道”),将原来所使用的Sybase,Sql Anywhere, MySql全都通通扔到了一边。在持续化构建过程中,因其尚未提供ant的第三方任务插件,因此需要清楚地了解在命令行下进行相应操作的方法,再通过<java>进行转化,进而针对其特点特作此小结。而大众化的知识,如驱动类名(org.hsqldb.jdbcDriver),如何在Java代码中进行连接,用户名(默认为”sa”)与密码(默认为””),“地球人都知道”,就不作详细介绍了。

1. HsqlDb自带工具
 org.hsqldb.util.DatabaseManager
 org.hsqldb.util.DatabaseManagerSwing
 org.hsqldb.util.Transfer
 org.hsqldb.util.QueryTool
 org.hsqldb.util.SqlTool
调用方法:java -cp hsqldb.jar org.hsqldb.util.DatabaseManager(在hsqldb.jar的当前路径下)

2. HsqlDb的数据库
 以文件形式存在。
 未指定文件名时,默认为"test",会产生以下几种文件
 test.properties
 test.script
 test.log
 test.data
 test.backup

3. HsqlDb数据库的类型
服务器模式:允许多个连接
    Server模式: jdbc:hsqldb:hsql://localhost/<dbname>
    Web Server模式: jdbc:hsqldb:http://<hostname>/<dbname>
    Servlet模式: 只能通过Tomcat等服务器提供服务
独占模式:只允许一个连接
    jdbc:hsqldb:file:<dbname>
内存模式:存在于内存中,速度最快,但最后一个连接关闭或数据库关闭时,数据丢失。
    jdbc:hsqldb:mem:<dbname>

4. HsqlDb的启动
 当服务器启动时,如果在指定的路径中找不到相应的数据库名称,会自动创建数据库。
 未指定路径及文件名,则在执行java命令的当前路径下创建test数据库

下面举几个例子。下载HsqlDb后,将其解压到某个文件夹下面,假设F:\temp\hsqldb。打开一个命令行窗口,执行

F: (回车)
cd F:\temp\hsqldb (回车)

将当前路径设为F:\temp\hsqldb。

 执行
java -classpath ./lib/hsqldb.jar org.hsqldb.Server
启动Server模式数据库,则在F:\temp\hsqldb下面新建test.lck、test.txt及test.properties三个文件。此三个文件组成了名为test的数据库。
 执行
java -classpath ./lib/hsqldb.jar org.hsqldb.Server -database.0 adb -dbname.0 adb
在F:\temp\hsqldb下面新建adb.lck、adb.txt及adb.properties三个文件。其中,由-database.0指定的adb是存放数据库的文件名,由-dbname.0指定的adb是对外提供连接的数据库名称(也称为别名),可用jdbc:hsqldb:hsql://localhost/adb进行连接。
 执行
java -classpath ./lib/hsqldb.jar org.hsqldb.Server -database.0 data/adb -dbname.0 adb
在F:\temp\hsqldb\data下面新建adb.lck、adb.txt及adb.properties三个文件。如果data这个文件夹不存在,会自动创建。与上面比较,存放数据库的路径变了,但别名未变,因此,也用jdbc:hsqldb:hsql://localhost/adb进行连接。

5. 执行SQL语句
执行SQL语句时,出于安全原因,需要在用户根目录(Windows XP中是C:\Documents and Settings\<username>,注意,不是”我的文档”)下面新建一个名为sqltool.rc文件。对于Server模式,其内容如下:

urlid localhost-sa
url jdbc:hsqldb:hsql://localhost/<dbname>
username sa
password

其中,url、username及password是我们所熟悉的数据库连接参数,而urlid是在执行SQL语句时需要用于验证用户身份的id。此值可相对任意取,但在同一sqltool.rc文件中必须唯一。使用方法见下面。

5.1 通过命令行执行SQL语句

java -jar ./lib/hsqldb.jar --sql " INSERT INTO Person VALUES(1, ‘Mike’);select * from Person " localhost-sa

通过调用java命令,执行hsqldb.jar,将参数设为--sql,表示要执行SQL语句。SQL语句在两个以上时,用括号包围,之间以分号隔开。SQL语句之后紧跟着的就是sqltool.rc中的urlid。这里的urlid必须与sqltool.rc致时才能执行SQL语句。这样可在一定程度上防范SQL注入侵犯。

5.2 通过SQL文件执行SQL语句

java -jar ./lib/hsqldb.jar localhost-sa sample.sql

sample.sql为SQL文件名,跟在urlid之后。因其有一定特点,特列出全部内容,以便说明:

/*
    $Id: sample.sql,v 1.5 2005/05/02 15:07:27 unsaved Exp $
    Examplifies use of SqlTool.
    PCTASK Table creation
*/

/* Ignore error for these two statements */
\c true
DROP TABLE pctasklist;
DROP TABLE pctask;
\c false

\p Creating table pctask
CREATE TABLE pctask (
    id integer identity,
    name varchar(40),
    description varchar,
    url varchar,
    UNIQUE (name)
);

\p Creating table pctasklist
CREATE TABLE pctasklist (
    id integer identity,
    host varchar(20) not null,
    tasksequence int not null,
    pctask integer,
    assigndate timestamp default current_timestamp,
    completedate timestamp,
    show bit default true,
    FOREIGN KEY (pctask) REFERENCES pctask,
    UNIQUE (host, tasksequence)
);

\p Granting privileges
GRANT select ON pctask TO public;
GRANT all ON pctask TO tomcat;
GRANT select ON pctasklist TO public;
GRANT all ON pctasklist TO tomcat;

\p Inserting test records
INSERT INTO pctask (name, description, url) VALUES (
    'task one', 'Description for task 1', 'http://cnn.com');
INSERT INTO pctasklist (host, tasksequence, pctask) VALUES (
    'admc-masq', 101, SELECT id FROM pctask WHERE name = 'task one');

commit;

说明:
 以/* …… */包围的内容为注解部分
 \c true意思为,即使有错误,也是继续执行。因此,对于”DROP TABLE pctasklist”,即使pctasklist表不存在,无法删除该表而出错,也会继续执行下面的SQL语句。
 \c false则相反,意思为,对于下面的SQL语句,出果出错,马上终止执行。
 \p为打印信息,此信息在将SQL语句输出到其他文件中时,将按原文输出。
 当执行到GRANT all ON pctask TO tomcat;时,由于tomcat的schema(用户或用户组)不存在,出错,后面的语句将不再执行,包括最后一行commit语句。
 默认情况下,SQL文本中的SQL语句在执行完毕后不会自动提交,因此需要在最后用commit;提交事务。但由于之前的SQL语句已经出错,因此这条语句在这里形同虚设,事务将回滚。

 

6. HsqlDb的关闭
根据5.1,在HsqlDb8.0中,可通过发送shutdown的SQL语句来关闭数据库服务器:

java -jar ./lib/hsqldb.jar --sql "shutdown" localhost-sa


7. 输出结果

输出日志。我们使用上面的语句来输出报表:

java -jar ./lib/hsqldb.jar localhost-sa sample.sql > log.txt

使用”>”符号,将结果输出至当前路径的log.txt。执行终止后,log.txt的内容如下:

Continue-on-error is set to: true          /* 对应于\c true */
Continue-on-error is set to: false         /* 对应于\c false */
Creating table pctask                  /* 对应于\p */
Creating table pctasklist               /* 对应于\p */
Granting privileges                   /* 对应于\p */

通过\o指令输出SQL查询结果。
在HsqlDb\src\org\hsqldb\sample文件夹下有一sampledata.sql文件,里面存放了许多生成数据库及插入数据的语句。我们先通过它来插入记录。执行以下语句:

java -jar ./lib/hsqldb.jar localhost-sa ./src/org/hsqldb/sample/sampledata.sql

然后,在F:\temp\hsqldb文件夹下面创建一个名为querydata.sql的文件,内容如下:

\o report.txt
select * from Product;
COMMIT;

其中,在第一行的”\o report.txt”中,”\o”为输出查询结果指令,将结果存放在当前路径的report.txt中。执行下面的语句:

java -jar ./lib/hsqldb.jar localhost-sa querydata.sql

执行后,除了在屏幕输出我们想要的结果外,HsqlDb还在当前路径下生成一个report.txt文件,里面除了在屏幕上显示的结果外,还在第一行中自动加上时间及生成工具:

# Sat Apr 29 02:26:31 CST 2006.  Query output from org.hsqldb.util.SqlFile.
ID  NAME               PRICE
--  -----------------  -----
0  Iron Iron            5.4
1  Chair Shoe          24.8
2  Telephone Clock     24.8
……

如果以上语句再执行一遍,则会将查询结果添加到report.txt的末端,而原来的查询结果依然保留。

除了文本文件,我们还可以输出html格式的网页报表。将querydata.sql内容修改如下:

\H
\o report.html
select * from Product;
COMMIT;

“\H”指令将生成html格式的报表,而”\o”指令后面的report也相应地改成了.html文件。再次执行上面的SQL语句:

java -jar ./lib/hsqldb.jar localhost-sa querydata.sql

屏幕输出了report.html的源码,同时也生成了report.html文件。在querydata.sql文件中,我们打开了”\H”的指令,如果想把它改为默认的文本格式,再设一次”\H”就行了。

Html文件也是自动添加的格式。

可以通过”\p”指令添加表头、、”\d”指令过滤字段等。

8. Ant持续化构建
有了上面的基础,我们可以换成ant指令,以便实现持续化构建。在F:\temp\hsqldb下新建一个build.xml文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project name="appfuse" basedir="." default="help">

<property name="hsqldb.path" value="lib/hsqldb.jar" />
<property name="database.dir" value="db" />
<property name="database.name" value="testdb" />
<property name="database.urlid" value="localhost-sa" />
<property name="datafile.dir" value="src/org/hsqldb/sample/sampledata.sql" />
<property name="queryfile.name" value="querydata.sql" />
<property name="reportoutput.dir" value="report" />
<property name="reportfile.name" value="genreport.sql" />

<target name="help"
  description="Show help information">
  <echo level="info">HsqlDB Utils</echo>
  <echo level="info">================================================================</echo>
  <echo level="info">=> browseServer:   Query HsqlDb with its DatabaseManagerSwing ==</echo>
  <echo level="info">=> clean:          Clean all output results                   ==</echo>
  <echo level="info">=> help:           Show this information                      ==</echo>
  <echo level="info">=> shutdownServer: Shutdown HsqlDb Server                     ==</echo>
  <echo level="info">=> startServer:    Start HsqlDb Server in Server mode         ==</echo>
  <echo level="info">=> populate:       Insert sample data                         ==</echo>
  <echo level="info">=> queryData:      Query data from database                   ==</echo>
  <echo level="info">=> report:         Make data report                           ==</echo>
  <echo level="info">================================================================</echo>
</target>

    <target name="startServer"
        description="Start HsqlDb Server">
        <echo level="info">Starting HsqlDb Server...</echo>
        <java
            classname="org.hsqldb.Server"
            classpath="${hsqldb.path}"
            fork="true"
            failonerror="true">
            <arg value="-database.0" />
            <arg value="file:${database.dir}/${database.name}" />
            <arg value="-dbname.0" />
            <arg value="${database.name}" />
        </java>
    </target>
   
    <target name="shutdownServer">
     <echo level="info">Shutdown HsqlDb Server...</echo>
  <java
   jar="${hsqldb.path}"
   classpath="${hsqldb.path}"
   fork="true"
            failonerror="true">
            <arg value="--sql" />
            <arg value="shutdown" />
            <arg value="localhost-sa" />
        </java>
    </target>
   
    <target name="browseServer"
        description="Browse Database Server">
        <echo level="info">Opening HsqlDb ManagerSwing...</echo>
        <java
         classname="org.hsqldb.util.DatabaseManagerSwing"
         classpath="${hsqldb.path}"
         fork="true"
         failonerror="true">
            <arg value="-url"/>
            <arg value="jdbc:hsqldb:hsql://localhost/${database.name}" />
        </java>
    </target>

    <target name="populate"
     description="Insert sample data">
  <java
   jar="${hsqldb.path}"
   classpath="${hsqldb.path}"
   fork="true"
            failonerror="true">
            <arg value="${database.urlid}" />
            <arg value="${datafile.dir}" />
        </java>
    </target>
   
    <target name="queryData"
     description="Query data from database">
  <java
   jar="${hsqldb.path}"
   classpath="${hsqldb.path}"
   fork="true"
            failonerror="true">
            <arg value="${database.urlid}" />
            <arg value="${queryfile.name}" />
        </java>
    </target>
   
    <target name="report"
     description="Make data report">
        <mkdir dir="${reportoutput.dir}" />
  <java
   jar="${hsqldb.path}"
   classpath="${hsqldb.path}"
   fork="true"
            failonerror="true">
            <arg value="${database.urlid}" />
            <arg value="${reportfile.name}" />
        </java>
    </target>
   
    <target name="clean"
     description="Clean all outputs results">
     <delete dir="${reportoutput.dir}" />
    </target>
</project>

你可能感兴趣的:(sql,tomcat,jdbc,SQL Server,HSQLDB)