數(shù)據(jù)庫環(huán)境配置和使用
首先從http://www.hsqldb.org/下載一個hsqldb的穩(wěn)定版本,解壓后可以瀏覽解壓目錄下的index.html,它描述了各個目錄所包含內(nèi)容,在doc段里有一個重要的鏈接User Guide: index.html,有空好好研究吧!
數(shù)據(jù)庫實例創(chuàng)建
在hsqldb的管理中,如果啟動的數(shù)據(jù)庫文件不存在,就新建該數(shù)據(jù)庫文件。
Hsldb啟動
Hsqldb的啟動模式有三種主要模式,其他參見User Guide:
l???????
Server
該模式就像啟動mysql、oracle等數(shù)據(jù)庫一樣,數(shù)據(jù)庫啟動后作為一個服務(wù)存在,其他數(shù)據(jù)庫工具可以通過jdbc的方式訪問他,這是我們最熟悉的模式。啟動腳本如下:
java -cp hsqldb.jar org.hsqldb.Server -database.0 ./db/test -dbname.0 test |
后面參數(shù):
-database.n 數(shù)據(jù)庫文件(其他數(shù)據(jù)庫中對應(yīng):數(shù)據(jù)庫實例)地址,支持相對路徑,注意使用反斜杠
-dbname.n 數(shù)據(jù)庫文件的訪問同義詞,就是用這個名稱訪問數(shù)據(jù)庫的
server模式j(luò)dbc訪問方式:
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost:9002/test", "sa", "");
|
可以啟動多個數(shù)據(jù)庫文件,例如:
java -cp hsqldb.jar org.hsqldb.Server -database.0 ./db/test0 -dbname.0 test0? -database.1 ./db/test1 -dbname.1 test1 |
l???????
In-Process (Standalone)
該模式更接近于文件型數(shù)據(jù)庫這個概念,當(dāng)你訪問時他就啟動,這種模式訪問速度最快,缺點是只能當(dāng)前訪問線程使用,其他數(shù)據(jù)庫工具不能同時訪問。例如jdbc訪問:
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb", "sa", "");
|
l???????
In-Memory
顧名思義,內(nèi)存中的數(shù)據(jù)庫,你所做的數(shù)據(jù)庫ddl、dml不會寫入磁盤,也是當(dāng)你訪問時他就啟動。例如jdbc訪問:
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:aname", "sa", "");
|
Hsqldb 管理工具
hsqldb.jar中自帶了一個數(shù)據(jù)庫管理工具:DatabaseManagerSwing(Swing界面,還有一個是Awt界面的:DatabaseManager),該工具可以通過jdbc訪問多種數(shù)據(jù)庫。
我們使用server模式啟動hsqldb數(shù)據(jù)庫,然后運行下列命令:
java -cp hsqldb.jar org.hsqldb.util.DatabaseManagerSwing |
就可打開主界面
連接時注意選擇:Type,應(yīng)該是HSQL Database Engine Server
對于第一次使用可以使用它自帶的功能,創(chuàng)建一些測試表,挺好的吧:
[圖片1]
好了你就可以寫些語法數(shù)據(jù)庫語法了:
[圖片2]
你可以直接關(guān)閉它但數(shù)據(jù)庫不受影響,仍然啟動著。
[圖片3]
Hsldb關(guān)閉
對于任何一種啟動模式,都可以在輸入sql腳本的狀態(tài)輸入:SHUTDOWN 或 SHUTDOWN COMPACT 語法來關(guān)閉數(shù)據(jù)庫。
對于In-process和In-memory這兩種模式只要所有的連接關(guān)閉了,數(shù)據(jù)庫也就關(guān)閉了。
Server模式參數(shù)設(shè)置
在server模式下可以設(shè)置一些參數(shù),主要的例如訪問端口,可以參見User Guide的第四章高級屬性,一般我們可以在啟動腳本的目錄下編輯一個server.properties,內(nèi)容如下:
server.port=9002
server.trace=true |
Sqltool工具使用
在目錄src\org\hsqldb\sample下有一個sqltool.rc文件,將其拷貝到工具使用命令目錄中,修改如下片斷:
urlid test
url jdbc:hsqldb:hsql://localhost:9002/test
username sa
password |
其中urlid就是啟動hsqldb的參數(shù)-dbname.0 test
然后使用如下命令:
java -jar hsqldb.jar --sql "select * from customer" --rcfile sqltool.rc test |
大家可以通過“java -jar hsqldb.jar –help”看看其他的參數(shù)
好了給大家一個整理的壓縮包[下載],別忘了裝jdk1.4
在web應(yīng)用中嵌入hsqldb
寫一個Listener
將hsqldb嵌入到web應(yīng)用首要解決的問題是數(shù)據(jù)庫的啟動和關(guān)閉問題,參考springside項目的方法加入一個容器級的Listener,代碼如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hsqldb.Server;
/**
?* 該類的職責(zé)是在WebApp啟動時自動開啟HSQL服務(wù). 依然使用Server方式,不受AppServer的影響.
?*
?* @author frank
?* @author calvin
?*/
public class HsqlListener implements ServletContextListener {
??? protected Logger logger = Logger.getLogger(getClass());
??? /*
???? * (非 Javadoc)
???? *
???? * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
???? */
??? public void contextInitialized(ServletContextEvent sce) {
??????? logger.info(" ============= HsqlListener initialize...");
??????? // 獲得數(shù)據(jù)庫文件訪問路徑
??????? String path = getDbPath(sce);
??????? if (!path.endsWith("/"))
??????????? path = path + "/";
??????? if (StringUtils.isEmpty(path)) {
??????????? logger.info(" ============= Can't get hsqldb.path from web.xml Context Param");
??????????? return;
??????? }
??????? logger.debug("hsqldb_path:" + path);
??????? // 數(shù)據(jù)庫文件名
??????? String dbName = sce.getServletContext().getInitParameter("hsql.dbName");
??????? if (StringUtils.isEmpty(dbName)) {
??????????? logger.info(" ============= Can't get hsqldb.dbName from web.xml Context Param");
??????????? return;
??????? }
??????? // 數(shù)據(jù)庫訪問端口
??????? int port = -1;
??????? try {
??????????? port = Integer.parseInt(sce.getServletContext().getInitParameter("hsql.port"));
??????? } catch (Exception e) {
??????????? e.printStackTrace();
??????????? return;
??????? }
??????? // 啟動數(shù)據(jù)庫
??????? startServer(path, dbName, port);
??? }
??? /**
???? * 獲得數(shù)據(jù)庫文件訪問路徑
???? *
???? * @param sce
???? * @return
???? */
??? private String getDbPath(ServletContextEvent sce) {
??????? String path = sce.getServletContext().getInitParameter("hsql.dbPath");
??????? if (path.startsWith("{user.home}")) {
??????????? path = path.replaceFirst("\\{user.home\\}", System.getProperty("user.home").replace('\\', '/'));
??????? }
??????? if (path.startsWith("{webapp.root}")) {
??????????? path = path.replaceFirst("\\{webapp.root\\}", sce.getServletContext().getRealPath("/").replace('\\', '/'));
??????? }
??????? return path;
??? }
??? /**
???? * 啟動數(shù)據(jù)庫
???? *
???? * @param dbPath
???? * @param dbName
???? * @param port
???? */
??? private void startServer(String dbPath, String dbName, int port) {
??????? Server server = new Server();
??????? server.setDatabaseName(0, dbName);
??????? server.setDatabasePath(0, dbPath + dbName);
??????? if (port != -1)
??????????? server.setPort(port);
??????? server.setSilent(true);
??????? server.setTrace(true);
??????? server.start();
??????? logger.info(" ============= hsqldb started...");
??????? // 等待Server啟動
??????? try {
??????????? Thread.sleep(800);
??????? } catch (InterruptedException e) {
??????????? e.printStackTrace();
??????? }
??? }
??? /*
???? * (非 Javadoc)
???? *
???? * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
???? */
??? public void contextDestroyed(ServletContextEvent sce) {
??????? logger.info(" ============= HsqlListener destroyed...");
??????? Connection conn = null;
??????? try {
??????????? Class.forName("org.hsqldb.jdbcDriver");
??????????? conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost:9002/weed", "sa", "sa");
??????????? Statement stmt = conn.createStatement();
??????????? stmt.executeUpdate("SHUTDOWN;");
??????????? logger.info(" ============= hsqldb shutdown...");
??????? } catch (Exception e) {
??????????? e.printStackTrace();
??????? }
??? }
} |
增加web.xml配置
web.xml配置增加如下:
…
<!--HSQLDB Listener的參數(shù),隨WebApp啟動停止的Listener
??????? {user.home}??????? System.getProperty("user.home")
??????? {webapp.root}????? servletContext.getRealPath("/")
??? -->
??? <context-param>
??????? <param-name>hsql.dbPath</param-name>
??????? <param-value>{webapp.root}/WEB-INF/dbms/db</param-value>
??? </context-param>
??? <context-param>
??????? <param-name>hsql.dbName</param-name>
??????? <param-value>weed</param-value>
??? </context-param>
??? <context-param>
??????? <param-name>hsql.port</param-name>
??????? <param-value>9002</param-value>
</context-param>
…
<!--
??? 控制HSQLDB隨Web App 啟動停止
??? -->
??? <listener>
??????? <listener-class>test.HsqlListener</listener-class>
??? </listener> |
好了,你現(xiàn)在可以像訪問mysql、oracle等其他數(shù)據(jù)庫一樣配置jdbc連接訪問hsqldb了,在HsqlListener中有一個類org.hsqldb.Server,有空你可以研究一下他的源碼。