已经习惯在开发和演示环境使用h2来代替大号数据库很长时间了。 Embedded 的启动方式,快速,小巧,该有的都有了,sql和oracle, db2,mysql兼容性都不错。唯一的问题是,Embedded 方式运行时无法使用工具来查看数据情况,虽然可以通过UT来做测试,但是有些时候还是挺不方便的。

今天浏览h2的网站,发现文档已经做了更新,现在H2的使用模式支持三种
 * Embedded mode (local connections using JDBC)
 * Remote mode (remote connections using JDBC or ODBC over TCP/IP)
 * Mixed mode (local and remote connections at the same time)
 
使用模式增加了一种MixedMode模式,即可以使用Embedded的方式来使用h2的同时, 还可以再启动一个服务来接受远程连接。

看了一下,实现还是很简单的

 

public class H2Server {
 
private int port = 9081;
 
private Server server = null;
 
protected final Log logger = LogFactory.getLog(H2Server.class);

 
 
public int getPort() {
  
return port;
 }


 
public void setPort(int port) {
  
this.port = port;
 }


 
public void start() {
  
try {
   server 
= Server.createTcpServer( new String[] "-tcpPort",  "" + port }).start();
   logger.info(
"start the H2 MixedMode server on port:" + port);
  }
 catch (SQLException e) {
   e.printStackTrace();
   logger.error(e);
   logger.error(
"fail to start the h2 Assist server..");
  }

 }

 
 
public void stop() {
  
if (server != null{
   server.shutdown();
  }

 }



在应用启动时找个地方起来, 现在就可以用squirrel之类的客户端工具通过“jdbc:h2:tcp://localhost:9081/~/test”的格式进行连接了。

这段代码其实和remote mode没有任何区别,不过在mixed mode中,remote访问只是辅助手段,所以启动点可以在任何位置,这样配置要灵活一些。在我的应用里,我就先对主连接做判断,是嵌入的h2方式时才启动这个服务。也可以弄个配置参数决定是否要启动。

if (dbc.isH2()) {
   logger.info(
" use h2 datbase ");
   
if (!dbc.checkTableIfExist()) {
    logger.info(
" create h2 db table now ");
    dbc.createTable();
    logger.info(
" insert  h2 db init data ");
    dbc.insertInitData();
   }

   h2MixedModeServer 
= new H2Server();
   
new Thread() {
    
public void run() {
     h2MixedModeServer.start();
    }

   }
.start();
  }


h2的文档中代码样例的内容较少,要自己查看test目录下的测试代码,顺便试了一下,其实1年前的版本就已经支持此功能了,只是文档未做同步更新而已,这也算是开源项目的一个共同问题吧。

如果觉得第三方工具不够专业和兼容,也可以使用h2自身带的管理Console,找到h2发布包的bin目录下的h2.bat, 运行会打开一个浏览器窗口,在里面设置连接即可, 完全基于web方式操作,功能挺全的。

作者还真是超级小强,顺手用不到100k的代码实现了一个 web container。本着八卦到底的原则,顺便d了一下他是怎么实现系统托盘和启动浏览器的。

 

if (osName.startsWith("Windows")) {
                Runtime.getRuntime().exec(
"rundll32 url.dll,FileProtocolHandler " + url);
            }
 else if (osName.startsWith("Mac OS X")) {
                
// Runtime.getRuntime().exec("open -a safari " + url);
                
// Runtime.getRuntime().exec("open " + url + "/index.html");
                Runtime.getRuntime().exec("open " + url);
            }
 else {
                System.out.println(
"Please open a browser and go to "+ url);
            }


系统托盘使用了java6的特性,不过做了一个判断。 小强同志此处有点失误,干嘛不再做个判断,如果是6版本则使用Desktop来启动浏览器,这样可以增加对linux的支持。