HyperSQL调研学习文档(一)

2022-04-08 00:00:00 路径 数据库 模式 连接 文件

近调研HyperSQL,把整理的资料记录一下,并分享给大家,由于时间略紧,内容肯定有遗漏和谬误的地方,欢迎大家指正。本人也会持续的修改更新。



1.HyperSQL使用简介
1.1 HyperSQL数据库存储方式说明


每一个HyperSQL的数据库被称为一个目录(catalog),根据数据库存储方式不同分为几种:
• mem: 整个的保存在RAM内存中-在JVM进程的生命周期之外不做任何的持久化。mem:目录可以用于测试数据或者充当一个应用的复杂的缓存。这种库没有关联任何文件。


• file: 保存在文件系统中。一个file:目录包含2-6个文件,全部命名为相同的名字但是使用不同的扩展名,位于相同的文件目录。例如:名为"test"的数据库包含如下的文件:

test.properties
test.script
test.log
test.data
test.backup
test.lobs
properties文件包含了关于该数据库的几个设置。script文件包含了表和别的数据库对象的定义,还有非cached表的数据。log文件包含了本库的近变更。data文件包含了cached表的数据。
backup文件是一个压缩的备份,是关于data文件的上次已知的一致状态的备份。所有这些文件都是很重要的,并且绝不能删除。对于有些目录(catalog)而言,test.data和test.backup文件不会出现。除了上述的这些文件,一个HyperSQL数据库可能连接到任何格式化的text文件,例如一个CSV列表,该text文件可位于磁盘上的任何位置。
当"test"目录(catalog)打开,一个test.log文件就被用来记录对数据的修改。该文件在目录正常关闭(SHUTDOWN)时被删除。否则(非正常关闭)在下一次启动时该文件就会被用来恢复这些修改。
test.lck文件也被用于记录数据库打开的事实。它在数据库正常关闭时被删除。
注意:关闭时,当引擎关闭数据库时,会创建后缀为.new的临时文件,然后命名为跟上面列出来的一样的名字。这些文件不应被用户删除。在下一次启动时,所有这些文件都会被数据库引擎重命名或删除。在一些情况下,test.data.xxx.old文件会被数据库引擎创建并在后续重启时删除。用户可以删除这些test.data.xxx.old文件。


• res: 保存在Java资源文件中,例如一个Jar包内并且是只读的。一个res:目录包含了对于一个小的,只读的数据库相关的文件,这些文件可以被保存在Java代码(例如一个ZIP或JAR)中并作为Java应用程序的一部分被发布。

1.2 HyperSQL数据库服务模式
1.2.1 进程内连接数据库

一般而言,JDBC用来处理对数据库的所有访问。通过建立一个跟数据库的连接来完成,然后使用返回的java.sql.Connection对象的各种方法来访问数据。访问一个进程内数据库就是通过JDBC开始的,并在连接URL中指定数据库的路径。例如,如果file:类型数据库的名字是"testdb"并且其文件就位于运行你的应用的命令所在位置,下面的代码就用来连接:



Connection c = DriverManager.getConnection("jdbc:hsqldb:file:testdb", "SA", "");
数据库文件路径的格式可以使用斜杠,在Windows主机和Linux主机中都是如此。因此,相对路径或指向同一磁盘的相同目录的路径是相同的。例如如果你的数据库路径在Linux下是/opt/db/,包含一个库testdb(就是名为testdb.*的若干文件),那么数据库文件的路径是/opt/db/testdb。如果你在一个Window主机上的C盘创建一个相同的目录结构,你可以使用相同的URL在Windows和Linux上:


Connection c = DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb", "SA", "");
当使用相对路径时,这些路径会相对于启动Java虚拟机的shell命令执行的路径。参照JDBCConnection的Javadoc以获得更多细节。
对于file:类型的数据库,在库创建的时候或次connection的时候,路径和数据库名会以大小写敏感的方式被对待。但是当再一次连接已打开的数据库时,仅仅使用大小写不同的path和name,会连接到一个已存在的打开的库。这个措施是很有必要的,因为在Windows下这两个路径是相同的。


一个mem:数据库由mem:协议指定。对于mem:数据库,路径是一个简单的名字。若干mem:库可以同时存在,用他们的名字来区分。下面的例子中,库叫做"mymemdb":

Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:mymemdb", "SA", "");


一个res:数据库,由res:协议指定。基于它是一个Java资源,数据库路径是一个Java URL(类似于类的路径)。下面例子中,"resdb"是库文件的根名子,这些库文件存放在classpath(也可能是一个Jar)下的"org/my/path"中。一个Java资源以一种压缩的格式存储,使用的时候在内存中被解压。基于此,res:数据库不应该包含大量的数据并且总是只读的。

Connection c = DriverManager.getConnection("jdbc:hsqldb:res:org.my.path.resdb", "SA", "");
一旦对于数据库的进程内连接被建立,一些常规数据结构会被初始化,并且一些帮助线程会被启动起来。在这之后,连接的建立以及对于JDBC方法的调用执行起来就像他们是做出调用的应用的一部分一样。
当执行SQL命令"SHUTDOWN",关于数据库的全局的结构和helper线程统统被销毁。
注意,对于指定的file:数据库,一次只能有一个Java进程做出进程内连接。然后,如果file:数据库被设置为只读,或者如果连接被设置为res:库,那么可以从多个Java进程中做出进程内连接。



1.2.2 服务器模式

对于绝大多数应用来说,进程内连接更快,因为数据不用转换和通过网络传送。主要的缺点是默认情况下很难从你应用以外的地方连上这个数据库。结果就是当你程序运行的时候,你不能通过类似于Database Manager这样的外部工具来检查数据库内容。
服务器模式提供了大的可访问性。数据库引擎运行在一个JVM里并打开一个或多个进程内的目录(in-process catalogs)。它监听着来自于同主机或网络上不同主机上的程序的连接。并将这些连接转化为对数据库的进程内连接。
若干不同的程序可以连接到服务器然后获取或更改信息。应用程序(客户端)使用HyperSQL JDBC驱动连接到服务器。在大部分服务器模式里,服务器可以维护不限数量的库,这些库在运行服务器时指定,或接到一个连接请求时也可指定。
在开发过程中,服务器模式也是数据库运行的更好模式。它允许你在程序运行时从一个独立的可访问数据库设施中查询数据。
基于client和server通信的协议,有三种服务器模式。在下面会对它们进行简要的讨论。


• HyperSQL HSQL Server

这是运行一个数据库服务器的方案,并且是快的方案。该模式使用了一个专有的通信协议。一个和上面讨论的运行工具相似的命令用来启动服务端。下面关于启动服务端的命令的例子启动了默认有一个名为"mydb.*"库的数据库,该库使用了一个公开的名字"xdb"。公开名字向用户隐藏了库的文件名。

java -cp ../lib/hsqldb.jar org.hsqldb.server.Server --database.0 file:mydb --dbname.0 xdb
命令行参数--help可用来获得可用参数列表。


• HyperSQL HTTP Server

这种访问方式是在运行数据库服务端的主机被限制为运行HTTP协议的时候使用。使用这种方式的原因就是客户端或服务端主机的防火墙限制,如果没有这种限制就不应该使用。
HyperSQL HTTP服务器是一种特殊的web服务器,允许JDBC客户端通过HTTP连接。服务器也可以针对一些静态页面,作为一个小的通用意义上的web服务器。要启动一个HTTP服务器,替换上面例子中的命令行中的主类为下面的类:

org.hsqldb.server.WebServer
命令行参数--help可用来获得可用参数列表。

• HyperSQL HTTP Servlet

这种访问方式也用HTTP协议。当一个servlet引擎(或应用服务器)例如Tomcat或Resin提供数据库访问时使用这种方式。上述servlet引擎无法独立启动Servlet模式。需要把HSQLDB jar包中的Servlet类注册到应用服务器中,用来提供连接。通过应用服务器参数来指定数据库文件的路径。参考源文件:

src/org/hsqldb/server/Servlet.java
来查看细节。

HTTP服务模式和Servlet模式都可以在客户端通过JDBC driver来访问。它们没有为数据库提供一个web前端(例如管理端界面什么的)。Servlet模式可以服务于多个数据库(通过注册多个org.hsqldb.server.Servlet的bean)。
注意,当你在一个应用服务器中使用数据库引擎时,不会经常使用这种模式。在这种情况下,通常使用进程内连接到一个数据库目录,或者使用一个隔离的Server模式数据库。

1.3 连接到一个数据库服务
客户端可以通过不同的连接字符串来连接不同服务模式的数据库,并指定不同的存储格式:


1.3.1 使用InProcess模式

也就是说在Client端直接启动一个内置的DBMS,这种模式不需要专门启动服务端,在应用客户端直接使用如下的方式获得connection:

Connection c = DriverManager.getConnection("jdbc:hsqldb:file:testdb", "SA", ""); //file表示使用文件存储数据库
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb", "SA", "");//file:数据保存在文件
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:mymemdb", "SA", ""); //mem表示数据库只保存在内存
Connection c = DriverManager.getConnection("jdbc:hsqldb:res:org.my.path.resdb", "SA", ""); //res表示压缩保存classpath java或者zip包中,内存解压使用

1.3.2 使用remoteServer模式

这种模式需要首先启动一个Server:

Server server = new Server();
server.setPort(8743);
server.setDatabaseName(0, "test");
server.setDatabasePath(0, "mem:test;sql.enforce_strict_size=true;sql.restrict_exec=true");
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
然后客户端使用:

String url = "jdbc:hsqldb:hsql://localhost:8743/test";
Class.forName("org.hsqldb.jdbc.JDBCDriver");
Connection c = DriverManager.getConnection(url, "SA", "");
Statement stmnt = c.createStatement();
stmnt.execute("DROP TABLE T IF EXISTS;");
来建立连接并执行。

1.3.3 使用HTTP模式

这种模式需要首先启动一个WebServer:

WebServer server = new WebServer();
server.setPort(8743);
server.setDatabaseName(0, "test");
server.setDatabasePath(0, "mem:test;sql.enforce_strict_size=true;sql.restrict_exec=true");
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
然后客户端使用:

String url = "jdbc:hsqldb:http://localhost:8743/test";
Class.forName("org.hsqldb.jdbc.JDBCDriver");
Connection c = DriverManager.getConnection(url, "SA", "");
Statement stmnt = c.createStatement();
stmnt.execute("DROP TABLE T IF EXISTS;");
来建立连接并执行。

1.3.4 使用Servlet模式

这种模式需要一个Servlet容器,然后将org.hsqldb.server.Servlet注册到Servlet容器中,并配置相应的路径:

@Bean
public ServletRegistrationBean getDemoServlet(){
Servlet serv = new Servlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.setServlet(serv);
List<String> urlMappings=new ArrayList<String>();
urlMappings.add("/demo");//可以添加多个路径,指向同一个数据库
urlMappings.add("/demo1");
registrationBean.setUrlMappings(urlMappings);
registrationBean.setLoadOnStartup(1);
registrationBean.setName("myServletDB");

Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("hsqldb.server.database", "/home/wangd/data/hsqldbdata/mytestdb/mytest");
registrationBean.setInitParameters(initParameters);
return registrationBean;
}

然后客户端使用:



Class.forName("org.hsqldb.jdbc.JDBCDriver" );
Connection c = DriverManager.getConnection("jdbc:hsqldb:http://localhost:8080/demo", "SA", "");
Statement stmnt = c.createStatement();
stmnt.execute("DROP TABLE T IF EXISTS;");
来建立连接并执行。这种模式下一个servletBean只能配置使用一个database。可以通过配置多个Servlet Bean来支持多个database,此时注意需要添加

registrationBean.setName("myServletDB");
来给servletBean设置不同的名字,如果不设置,则配置的多个servletBean默认是相同名字相同类型的Bean,会自动merge为一个。
————————————————
版权声明:本文为CSDN博主「不动明王1984」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37962779/article/details/79126498

相关文章