- 浏览: 76137 次
- 性别:
- 来自: 石家庄
最新评论
-
xiaokang1582830:
我也遇到了同样的问题!之前在添加页面中这个问题都是可以解决,但 ...
让你的DIV在下拉框的上面 -
msongli:
[img][/img]
使用框架framset在IE6出现横向滚动条的解决方法 -
wyh2lxy1314:
待续了???
用FreeMarker做CMS模板--用户自定义模板 -
zxs19861202:
待续了??????
用FreeMarker做CMS模板--用户自定义模板 -
talangniao:
未完待续???
用FreeMarker做CMS模板--用户自定义模板
首先说一下hsqldb几个优点
- 轻巧,只有600多K,运行速度非常快。结合Hibernate数据库无关的特性,非常适合在项目开发的时候使用。
- 作为单元测试数据库。单元测试的时候,启动HSQLDB的file模式,数据不存盘,可以保证测试原子性。
- 来回复制,随身携带。
- 不需要安装,使用非常方便。
- 稳定,而且支持的数据量足够大。
- 小型项目作为现场数据库使用,不需要安装Oracle之类的大型DB,减轻了维护成本,并且,HSQLDB非常容易备份。
Hsqldb的各种好处就不再多说了,今天我们谈谈如何让它在我们日常开发中给我们带来更多的便捷。就像标题所说的,让Hsqldb随WebAPP一起启动。比平时用的DB2、Oracle、SQLServer... ...都要简洁方便许多,更重要从开发角度考虑Hsqldb的性能已经足够了。springside也是这么做的。
废话不多说了,现在开始:
我们借助Listener来实现此功能。
先给出一段该Listener的配置信息吧,*^_^*是存在web.xml里的。
xml 代码
- <context-param>
- <param-name>hsql.dbPath</param-name>
- <param-value>D:/db</param-value>
- </context-param>
- <context-param>
- <param-name>hsql.dbName</param-name>
- <param-value>mydb</param-value>
- </context-param>
- <context-param>
- <param-name>hsql.port</param-name>
- <param-value>9002</param-value>
- </context-param>
- <listener>
- <listener-class>
- systop.com.systopbase.common.HsqlStartListener
- </listener-class>
- </listener>
简单解释一下:
- hsql.dbPath: 采用绝对路径,且是固定的[D:/db]。而在实际应用中在这里我们更需要的是变量[或者说是相对路径],嘻嘻*^_^*不要着急,写这篇文章是为了让大家了解一下。在我们的systop-base项目中就采用了相对路径的方法,在那里你会有惊喜发现。
- hsql.dbName:需要说明的是在D:/db目录下确认有mydb.script和mydb.properties两个文件.
- hsql.port:设置hsqldb的端口,默认是9001,防止冲出使用9002。
接下来我们看看Listener是如何实现的:
java 代码
- package systop.com.systopbase.common;
- import org.hsqldb.Server;
- import org.springframework.util.FileCopyUtils;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.Statement;
- /**
- * 该类的职责是在WebApp启动时自动开启HSQL服务. 依然使用Server方式,不受AppServer的影响.
- */
- public class HsqlListener implements ServletContextListener {
- /**
- * Listener 初始化方法.
- */
- public void contextInitialized(ServletContextEvent sce) {
- String dbName = sce.getServletContext().getInitParameter("hsql.dbName");
- String path = sce.getServletContext().getInitParameter("hsql.dbPath");
- int port = -1;
- try {
- port = Integer.parseInt(sce.getServletContext().getInitParameter("hsql.port"));
- }catch(Exception e){
- port = 9001;
- }
- if (dbName == null || dbName.equals("")){
- System.out.println("Cant' get hsqldb.dbName from web.xml Context Param");
- return;
- }
- File dbDir = new File(path);
- if (!dbDir.exists()) {//判断目录是否存在
- if (!dbDir.mkdirs()) {//如果不存在创建,如果创建失败直接返回
- System.out.println("Can not create DB Dir for Hsql:" + dbDir);
- return;
- }
- }
- //以下代码是做数据库恢复的。我们把原始的数据库放在classpath下,当启动web的时候,检查目标
- //数据库是否存在,如果不存在,就把原始数据库复制为指定的数据库
- if (!path.endsWith("/")){
- path = path + "/";
- }
- File scriptFile = new File(path + dbName + ".script");
- File propertiesFile = new File(path + dbName + ".properties");
- if (scriptFile.exists() && propertiesFile.exists()){//判断数据文件是否存在
- this.startServer(path, dbName, port);
- } else{
- System.out.println("Connect failed:Connect Hsqldb error or database files not exits!");
- }
- }
- /**
- * 启动Hsqldb服务的方法。
- * @param dbPath 数据库路径
- * @param dbName 数据库名称
- * @param port 所使用的端口号
- */
- private void startServer(String dbPath, String dbName, int port) {
- Server server = new Server();//它可是hsqldb.jar里面的类啊。
- server.setDatabaseName(0, dbName);
- server.setDatabasePath(0, dbPath + dbName);
- if (port != -1){
- server.setPort(port);
- }
- server.setSilent(true);
- server.start();
- System.out.println("hsqldb started...");
- // 等待Server启动
- try {
- Thread.sleep(800);
- } catch (InterruptedException e){
- // do nothing
- }
- }
- /**
- * Listener销毁方法,在Web应用终止的时候执行"shutdown"命令关闭数据库.
- */
- public void contextDestroyed(ServletContextEvent arg0) {
- //这里就不用说了,自然是关闭数据库操作
- Connection conn = null;
- try {
- Class.forName("org.hsqldb.jdbcDriver");
- conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost:9002/bookstore", "sa", "");
- Statement stmt = conn.createStatement();
- stmt.executeUpdate("SHUTDOWN;");
- } catch (Exception e){
- // do nothing
- }
- }
- }
现在就部署到Web应用中去尝试一下吧。:)
评论
19 楼
javachs
2007-10-18
zwchen 写道
说点题外话,建议大家读读HSQLDB的源码,特别是jdbc driver(org\hsqldb\jdbc包)那部分,写得清晰易懂。读了它的部分源码,我自认为对下面一些问题理解深入了:
1、JDBC规范和JDBC实现的关系:怎么自己去设计一个规范,一种架构?我是否自己可以为某种数据设计jdbc driver,如何设计?想想php里面各数据库的函数库各自为政对程序移植性的影响,就知道jdbc规范有多么重要了。
2、JDBC协议:JDBC是基于socket之上的,数据包格式(org.hsqldb.Result)(mysql数据包格式公开了)?那么JMS数据包呢?其实,这也可以延伸到分布式协议的设计原理,如RMI、SOAP。其实,这些数据包格式和JSON、YAML这些message格式没有本质的区别,只不过应用范围不一样。
3、JDBC over HTTP:这样我们对RMI over IIOP, soap over HTTP, http tunnel原理有更深入的理解。
4、什么是long connection(jdbc的socket),什么是short connection(http),具体怎么实现?
3和4这些在HSQLDB的org.hsqldb.HTTPClientConnection类里有实现。
5、Java客户端和服务器端的通讯实现:jdbc driver就可以认为是一个java客户端类库。那么JMS client呢?还有,像mysql有各种语言的driver,原理是什么。
6、sql这种command、描述型语言究竟在数据库里面是个什么地位:sql是怎么传入jdbc driver,最终和database交互的?我们是否可以设计出另外一种command,形成一种行业标准,它在服务器和客户端怎么实现的。
以上我的表达可能有些晦涩,我只想表达一点:大家有兴趣就看看吧。有很多技术我们理解总是很模糊,当你深入到内部,忽然发现原来就这么回事。我们总觉得IoC很神秘,其实最简单的IoC容器,一个HashMap就够了。
1、JDBC规范和JDBC实现的关系:怎么自己去设计一个规范,一种架构?我是否自己可以为某种数据设计jdbc driver,如何设计?想想php里面各数据库的函数库各自为政对程序移植性的影响,就知道jdbc规范有多么重要了。
2、JDBC协议:JDBC是基于socket之上的,数据包格式(org.hsqldb.Result)(mysql数据包格式公开了)?那么JMS数据包呢?其实,这也可以延伸到分布式协议的设计原理,如RMI、SOAP。其实,这些数据包格式和JSON、YAML这些message格式没有本质的区别,只不过应用范围不一样。
3、JDBC over HTTP:这样我们对RMI over IIOP, soap over HTTP, http tunnel原理有更深入的理解。
4、什么是long connection(jdbc的socket),什么是short connection(http),具体怎么实现?
3和4这些在HSQLDB的org.hsqldb.HTTPClientConnection类里有实现。
5、Java客户端和服务器端的通讯实现:jdbc driver就可以认为是一个java客户端类库。那么JMS client呢?还有,像mysql有各种语言的driver,原理是什么。
6、sql这种command、描述型语言究竟在数据库里面是个什么地位:sql是怎么传入jdbc driver,最终和database交互的?我们是否可以设计出另外一种command,形成一种行业标准,它在服务器和客户端怎么实现的。
以上我的表达可能有些晦涩,我只想表达一点:大家有兴趣就看看吧。有很多技术我们理解总是很模糊,当你深入到内部,忽然发现原来就这么回事。我们总觉得IoC很神秘,其实最简单的IoC容器,一个HashMap就够了。
你讲得真不错特别是红色那部分,点睛之笔。我以前不知在那里看过有个老外维护着世界上一个最昂贵的HashMap产品。
18 楼
lunch
2007-05-22
可以做为嵌入式使用,具体最新版本的存储容量可以到官方查询。肯定会有惊喜
17 楼
pangyi
2007-05-22
hpsql的存储数据量足够大,是多大?
可以做为嵌入式数据库来使用吗?
可以做为嵌入式数据库来使用吗?
16 楼
zwchen
2007-05-16
说点题外话,建议大家读读HSQLDB的源码,特别是jdbc driver(org\hsqldb\jdbc包)那部分,写得清晰易懂。读了它的部分源码,我自认为对下面一些问题理解深入了:
1、JDBC规范和JDBC实现的关系:怎么自己去设计一个规范,一种架构?我是否自己可以为某种数据设计jdbc driver,如何设计?想想php里面各数据库的函数库各自为政对程序移植性的影响,就知道jdbc规范有多么重要了。
2、JDBC协议:JDBC是基于socket之上的,数据包格式(org.hsqldb.Result)(mysql数据包格式公开了)?那么JMS数据包呢?其实,这也可以延伸到分布式协议的设计原理,如RMI、SOAP。其实,这些数据包格式和JSON、YAML这些message格式没有本质的区别,只不过应用范围不一样。
3、JDBC over HTTP:这样我们对RMI over IIOP, soap over HTTP, http tunnel原理有更深入的理解。
4、什么是long connection(jdbc的socket),什么是short connection(http),具体怎么实现?
3和4这些在HSQLDB的org.hsqldb.HTTPClientConnection类里有实现。
5、Java客户端和服务器端的通讯实现:jdbc driver就可以认为是一个java客户端类库。那么JMS client呢?还有,像mysql有各种语言的driver,原理是什么。
6、sql这种command、描述型语言究竟在数据库里面是个什么地位:sql是怎么传入jdbc driver,最终和database交互的?我们是否可以设计出另外一种command,形成一种行业标准,它在服务器和客户端怎么实现的。
以上我的表达可能有些晦涩,我只想表达一点:大家有兴趣就看看吧。有很多技术我们理解总是很模糊,当你深入到内部,忽然发现原来就这么回事。我们总觉得IoC很神秘,其实最简单的IoC容器,一个HashMap就够了。
1、JDBC规范和JDBC实现的关系:怎么自己去设计一个规范,一种架构?我是否自己可以为某种数据设计jdbc driver,如何设计?想想php里面各数据库的函数库各自为政对程序移植性的影响,就知道jdbc规范有多么重要了。
2、JDBC协议:JDBC是基于socket之上的,数据包格式(org.hsqldb.Result)(mysql数据包格式公开了)?那么JMS数据包呢?其实,这也可以延伸到分布式协议的设计原理,如RMI、SOAP。其实,这些数据包格式和JSON、YAML这些message格式没有本质的区别,只不过应用范围不一样。
3、JDBC over HTTP:这样我们对RMI over IIOP, soap over HTTP, http tunnel原理有更深入的理解。
4、什么是long connection(jdbc的socket),什么是short connection(http),具体怎么实现?
3和4这些在HSQLDB的org.hsqldb.HTTPClientConnection类里有实现。
5、Java客户端和服务器端的通讯实现:jdbc driver就可以认为是一个java客户端类库。那么JMS client呢?还有,像mysql有各种语言的driver,原理是什么。
6、sql这种command、描述型语言究竟在数据库里面是个什么地位:sql是怎么传入jdbc driver,最终和database交互的?我们是否可以设计出另外一种command,形成一种行业标准,它在服务器和客户端怎么实现的。
以上我的表达可能有些晦涩,我只想表达一点:大家有兴趣就看看吧。有很多技术我们理解总是很模糊,当你深入到内部,忽然发现原来就这么回事。我们总觉得IoC很神秘,其实最简单的IoC容器,一个HashMap就够了。
15 楼
andrewdu
2007-05-16
我直接把数据库启动好,一直在那里侦听着呢.
14 楼
arthurln
2007-05-16
不错,收藏了,不过可能永远用不上,呵呵
13 楼
fins
2007-05-16
springside 很早以前就实现了类似的方式,后来不再用了 不知道为什么
现在ecside里的例子也是类似的 但用的是h2dbase 呵呵
现在ecside里的例子也是类似的 但用的是h2dbase 呵呵
12 楼
lunch
2007-05-16
不错不错:)
很好,这样做很方便的是吧:)
很好,这样做很方便的是吧:)
11 楼
xyz20003
2007-05-16
我的HsqldbListener跟楼主同学的不太一样,没有把配置文件写进web.xml而是使用了一个hsqldb.properties
hsqldb.properties放在WEB-INF/classes/conf目录下
hsqldb.properties里用了一个${webapp.root}这样我就可以把数据库文件放在项目目录的db目录下了,让项目随同测试数据一同发布。
PS:这个代码的原型来自www.springside.org.cn为了自己的需求稍微改写了一点儿。:)
package anni.core.web.listener; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.hsqldb.Server; /** * 控制数据库的周期. * context启动的时候,启动hsqldb数据库服务器,context关闭时shutdown数据库服务器 * * @author Lingo * @version 1.0 * @since 2007-03-13 * @see javax.servlet.ServletContextListener * @web.listener */ public class HsqldbListener implements ServletContextListener { /** * 配置文件中的占位符,代表webapp发布后的根目录. */ public static final String TOKEN = "${webapp.root}"; /** * 等待数据库停止的最大时间. */ public static final int WAIT_TIME = 1000; /** * jdbc的url. */ private String url; /** * 登陆用户名. */ private String username; /** * 登陆密码. */ private String password; /** * 处理context初始化事件. * @param sce ServletContextEvent */ public void contextInitialized(ServletContextEvent sce) { try { Properties prop = new Properties(); prop.load(HsqldbListener.class.getResourceAsStream( "/conf/hsql.properties")); username = prop.getProperty("hsql.username"); password = prop.getProperty("hsql.password"); String databaseName = prop.getProperty("hsql.databaseName"); int port = Integer.parseInt(prop.getProperty("hsql.port")); String hsqlPath = prop.getProperty("hsql.path"); // FIXME: 因为要用到getRealPath方法获得路径,在使用war包发布的时候会出现问题 if (hsqlPath.startsWith(TOKEN)) { String webappRoot = sce.getServletContext().getRealPath("/"); hsqlPath = hsqlPath.substring(TOKEN.length()); //if(hsqlPath.charAt(0) == '/' || hsqlPath.charAt(0) == '\\') //{ // hsqlPath = hsqlPath.substring(1); //} hsqlPath = webappRoot + hsqlPath; } String databasePath = hsqlPath + "/" + databaseName; url = "jdbc:hsqldb:hsql://localhost:" + port + "/" + databaseName; Server server = new Server(); server.setDatabaseName(0, databaseName); // ServletContext sc = sce.getServletContext(); server.setDatabasePath(0, databasePath); server.setPort(port); server.setSilent(true); server.start(); Thread.sleep(WAIT_TIME); } catch (IOException ex) { System.out.println( "HsqldbListener : contextInitialized : error : " + ex); } catch (InterruptedException ex) { System.out.println( "HsqldbListener : contextInitialized : error : " + ex); } } /** * 处理context销毁事件. * @param sce ServletContextEvent */ public void contextDestroyed(ServletContextEvent sce) { try { Class.forName("org.hsqldb.jdbcDriver"); Connection conn = null; Statement state = null; try { // 向数据库发送shutdown命令,关闭数据库 conn = DriverManager.getConnection(url, username, password); state = conn.createStatement(); state.executeUpdate("SHUTDOWN;"); } catch (SQLException ex1) { System.err.println("关闭数据库时出现异常:" + ex1); } finally { // 确保关闭Statement if (state != null) { try { state.close(); state = null; } catch (SQLException ex1) { System.err.println(ex1); } } // 确保关闭Connection if (conn != null) { try { conn.close(); conn = null; } catch (SQLException ex1) { System.err.println(ex1); } } } } catch (ClassNotFoundException ex) { System.err.println( "HsqldbListener : contextDestoryed : error : " + ex); // ex.printStackTrace(); } } }
hsqldb.properties放在WEB-INF/classes/conf目录下
hsql.username=sa hsql.password= hsql.port=9002 hsql.path=${webapp.root}/db/ hsql.databaseName=test
hsqldb.properties里用了一个${webapp.root}这样我就可以把数据库文件放在项目目录的db目录下了,让项目随同测试数据一同发布。
PS:这个代码的原型来自www.springside.org.cn为了自己的需求稍微改写了一点儿。:)
10 楼
抛出异常的爱
2007-05-15
楼上格式不好看不明白
9 楼
hiwzg
2007-05-15
没有必要吧。
如果非要这么做的话,可以改变startServer方法。让他连接到本地数据库,启动,返回connection就可以了……
不过,为什么还要让程序启动的时候去自动启动hsqldb server呢,先启动好不就完了。
文章给出了在启动app的时候加载其他服务的方式,赞。
如果非要这么做的话,可以改变startServer方法。让他连接到本地数据库,启动,返回connection就可以了……
不过,为什么还要让程序启动的时候去自动启动hsqldb server呢,先启动好不就完了。
文章给出了在启动app的时候加载其他服务的方式,赞。
spiritfrog 写道
特殊情况就是可以偷懒了。
我看到这里是用的server模式,那么怎样换成in-process模式呢?
我看到这里是用的server模式,那么怎样换成in-process模式呢?
8 楼
抛出异常的爱
2007-05-15
lunch 写道
当然,在大多数情况下意义并不是特别大。在项目中也不是非用不可,但是这也算是为特殊情况的一种解决方案,你们觉得呢?
请畅所欲言
请畅所欲言
如果早看到你的帖子就好了。。。
很久以前有用过这种方式。
不过我们是写的 .bat匹处理方式。。加延迟。。。
PS:评你这贴为良好也是出于这个原因。
7 楼
spiritfrog
2007-05-15
特殊情况就是可以偷懒了。
我看到这里是用的server模式,那么怎样换成in-process模式呢?
我看到这里是用的server模式,那么怎样换成in-process模式呢?
6 楼
lunch
2007-05-15
当然,在大多数情况下意义并不是特别大。在项目中也不是非用不可,但是这也算是为特殊情况的一种解决方案,你们觉得呢?
请畅所欲言
请畅所欲言
5 楼
spiritfrog
2007-05-14
hsqldb是简单的好。
只是这样做似乎没有什么必要,多数情况下都会先开启数据库服务的。
只是这样做似乎没有什么必要,多数情况下都会先开启数据库服务的。
4 楼
shaucle
2007-05-14
# String dbName
# String path
# int port
要占三个<context-param>,用默认的properties不行么
# String path
# int port
要占三个<context-param>,用默认的properties不行么
3 楼
lunch
2007-05-14
这不仅仅是在测试的时候,试想一下。当数据量不是特别大的时候我们完全可以把hsqldb作为我们项目部署的db.这样以来就大大降低了复杂度。让用户使用起来更加方便啊
2 楼
giscat
2007-05-14
直接跑内存模式就好了嘛
1 楼
lunch
2007-05-14
自己顶一个
相关推荐
NULL 博文链接:https://locao.iteye.com/blog/371790
hsqldb确实是个好东西,对于系统演示,开发等都很方便。
hsqldb学习,包括了实例创建、数据库启动、server模式参数设置、数据库管理工具及sqltool工具使用。
简单的创建两个例子,如何创建hsqldb,如何使用hsqldb查询数据等。
hsqldb jdbc driver适合于hsqldb
HSQLDB 1.8.0
数据库连接 hsqldb1.7.1.jar
hsqldb的最新1.9.0版本,支持windows操作系统
hsqldb for jdk1.5因为hsqldb的2.0版本以上都是jdk1.6进行编译的,我提供的这个2.25版本的是jdk1.5编译的。
hsqldb jar
HSQLDB中文手册
hsqldb可能需要的额外jar包 Additional Jar files needed for hsqldb.
HSQLDB中文文档,能够提高数据的处理速度。
hsqldb-2.4.0
HyperSQL User Guide HyperSQL Database Engine (HSQLDB) 2.2 hsqldb-2.2.9用户手册
hsqldb 2 3 2 zip HyperSQL是用Java编写的一款SQL关系数据库引擎 它的核心完全是多线程的 支持双向锁和MVCC 多版本并发控制 几乎完整支持ANSI 92 SQL 支持常见数据类型 最新版本增加了对BLOB和CLOB数据的支持 最高...
HSQLDB数据库,经典啊
不用安装其他的数据库,直接启用内部内置的数据库demo。 HSQLDB_Client类用启动库 TestByJDBC设置参数 注意:修改自己电脑当前JDK版本
Hsqldb是一个开放源代码的JAVA数据库,其具有标准的SQL语法和JAVA接口,它可以自由使用和分发,非常简洁和快速。
hsqldb数据库下载,很好用,简易的内存数据库,特别适合初学者。