hsqldb是java版的简化数据库,代码量比较少,对于学习数据库的设计是一个比较好的选择,
对于derby代码量比较大,mysql c++更复杂,所以就通过学习hsqldb来学习数据库的设计。
在这里可以下载到源码http://hsqldb.org/,源码包下org.hsqldb.test有很多的测试类,大家可以从这里开始调试学习hsqldb。
HyperSQL 数据库叫catalog,根据数据库存储方式不同分为几种:
• mem: stored entirely in RAM - without any persistence beyond the JVM process's life
• file: stored in filesystem files
客户端可以通过连接串不同指定不同的存储格式
Connection c = DriverManager.getConnection("jdbc:hsqldb:file:testdb", "SA", "");
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包中,内存解压使用
java -cp ../lib/hsqldb.jar org.hsqldb.server.Server --database.0 file:mydb --dbname.0 xdb
HyperSQL HTTP Server http协议的服务器模式
java -cp ../lib/hsqldb.jar org.hsqldb.server.WebServer --database.0 file:mydb --dbname.0 xdb
servlet容器启动服务器HyperSQL HTTP Servlet
try {
Class.forName("org.hsqldb.jdbc.JDBCDriver" );
} catch (Exception e) {
System.err.println("ERROR: failed to load HSQLDB JDBC driver.");
e.printStackTrace();
return;
}
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb", "SA", "");
如果是hsql服务器模式则用:hsql:,http则用http://
Connection c = DriverManager.getConnection("jdbc:hsqldb:http://localhost/xdb", "SA", "");
使用ssl连接到hsql和 http 服务器
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsqls://localhost/xdb", "SA", "");
Connection c = DriverManager.getConnection("jdbc:hsqldb:https://localhost/xdb", "SA", "");
关闭服务器:使用参数shutdown=true,最后一个连接处理完了需要关闭服务器,会对内存数据进行处理(如果是文件的,则flush到文件),这个在测试场景下用得比较多。
Connection c = DriverManager.getConnection(
"jdbc:hsqldb:file:/opt/db/testdb;shutdown=true", "SA", "");
如果要重用已有的数据库,则用参数ifexists=true,如果数据库不存在,则抛异常。
Connection c = DriverManager.getConnection(
"jdbc:hsqldb:file:/opt/db/testdb;ifexists=true", "SA", "");
public void handleConnection(Socket s) {
Thread t;
Runnable r;
String ctn;
printWithThread("handleConnection(" + s + ") entered");
if (!allowConnection(s)) {
try {
s.close();
} catch (Exception e) {}
printWithThread("allowConnection(): connection refused");
printWithThread("handleConnection() exited");
return;
}
// Maybe set up socket options, SSL
// Session tracing/callbacks, etc.
if (socketFactory != null) {
socketFactory.configureSocket(s);
}
if (serverProtocol == ServerConstants.SC_PROTOCOL_HSQL) {
r = new ServerConnection(s, this);
ctn = ((ServerConnection) r).getConnectionThreadName();
} else {
r = new WebServerConnection(s, (WebServer) this);
ctn = ((WebServerConnection) r).getConnectionThreadName();
}
t = new Thread(serverConnectionThreadGroup, r, ctn);
t.start();
printWithThread("handleConnection() exited");
}
从server的main函数输出参数中主要有几个:maxConnections 最大连接数限制, isSilent是否显示所有query,isRemoteOpen是否支持远程打开,不支持,isDaemon是否守护模式,acl指定访问控制权限文件路径,指定ip地址的黑白名单。acl文件格式参考http://hsqldb.org/doc/2.0/guide/listeners-chapt.html#N15C79
* +-----------------+-------------+----------+------------------------------+
* | OPTION | TYPE | DEFAULT | DESCRIPTION |
* +-----------------+-------------+----------+------------------------------|
* | --help | | | prints this message |
* | --address | name|number | any | server inet address |
* | --port | number | 9001/544 | port at which server listens |
* | --database.i | [type]spec | 0=test | path of database i |
* | --dbname.i | alias | | url alias for database i |
* | --silent | true|false | true | false => display all queries |
* | --trace | true|false | false | display JDBC trace messages |
* | --tls | true|false | false | TLS/SSL (secure) sockets |
* | --no_system_exit| true|false | false | do not issue System.exit() |
* | --remote_open | true|false | false | can open databases remotely |
* | --props | filepath | | file path of properties file |
* +-----------------+-------------+----------+------------------------------+
maxConnections = serverProperties.getIntegerProperty(
ServerProperties.sc_key_max_connections, 16);
JavaSystem.setLogToSystem(isTrace());
isSilent =
serverProperties.isPropertyTrue(ServerProperties.sc_key_silent);
isRemoteOpen = serverProperties.isPropertyTrue(
ServerProperties.sc_key_remote_open_db);
isDaemon =
serverProperties.isPropertyTrue(ServerProperties.sc_key_daemon);
当然openDatabase里面就是根据参数指定的database文件打开对应的数据库。
在database类的reopen方法中有几个对象,就是数据库操作相关的对象,无非就是数据库对象名称管理,权限管理,用户管理,shema管理,session管理,事务管理,日志管理,检查点管理,后续一个一个分析。
/**
* Opens this database. The database should be opened after construction.
* or reopened by the close(int closemode) method during a
* "shutdown compact". Closes the log if there is an error.
*/
void reopen() {
boolean isNew = false;
setState(DATABASE_OPENING);
try {
nameManager = new HsqlNameManager(this);
granteeManager = new GranteeManager(this);
userManager = new UserManager(this);
schemaManager = new SchemaManager(this);
persistentStoreCollection =
new PersistentStoreCollectionDatabase();
isReferentialIntegrity = true;
sessionManager = new SessionManager(this);
collation = collation.newDatabaseInstance();
dbInfo = DatabaseInformation.newDatabaseInformation(this);
txManager = new TransactionManager2PL(this);
lobManager.createSchema();
sessionManager.getSysLobSession().setSchema(
SqlInvariants.LOBS_SCHEMA);
schemaManager.setSchemaChangeTimestamp();
schemaManager.createSystemTables();
// completed metadata
logger.openPersistence();
isNew = logger.isNewDatabase;
if (isNew) {
String username = urlProperties.getProperty("user", "SA");
String password = urlProperties.getProperty("password", "");
userManager.createFirstUser(username, password);
schemaManager.createPublicSchema();
lobManager.initialiseLobSpace();
logger.checkpoint(false);
}
lobManager.open();
dbInfo.setWithContent(true);
checkpointRunner = new CheckpointRunner();
} catch (Throwable e) {
logger.closePersistence(Database.CLOSEMODE_IMMEDIATELY);
logger.releaseLock();
setState(DATABASE_SHUTDOWN);
clearStructures();
DatabaseManager.removeDatabase(this);
if (!(e instanceof HsqlException)) {
e = Error.error(ErrorCode.GENERAL_ERROR, e);
}
logger.logSevereEvent("could not reopen database", e);
throw (HsqlException) e;
}
setState(DATABASE_ONLINE);
}
下一节分析handleConnection的处理