在WEB-INF目录中嵌入H2数据库

Dou*_*oug 6 jdbc web-inf h2

我有一个嵌入式H2数据库,我想把它放在Web应用程序的WEB-INF目录中.

在JDBC URL中引用它的正确方法是什么?

理想情况下,我想要一个适用于WAR和扩展WAR(如果可能)的解决方案.

谢谢您的帮助!

仅供参考,我尝试过以下方法:

jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES
Run Code Online (Sandbox Code Playgroud)

但这会导致:

org.h2.jdbc.JdbcSQLException: A file path that is implicitly relative to the current working directory is not allowed in the database URL "jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES". Use an absolute path, ~/name, ./name, or the baseDir setting instead. [90011-187]
Run Code Online (Sandbox Code Playgroud)

将其更改为:jdbc:h2:./ WEB-INF/data/myDB; CIPHER = AES

导致以下错误,这清楚地表明它试图将我的数据库放在Tomcat的bin目录中,而不是我想要的真正的WEB-INF目录:

org.h2.jdbc.JdbcSQLException: Error while creating file "C:/Program Files/Apache Software Foundation/Tomcat 7.0/bin/WEB-INF" [90062-187]
Run Code Online (Sandbox Code Playgroud)

Chr*_*HON 6

我设法让嵌入式解决方案在没有AES的情况下工作:

try {
    Class.forName("org.h2.Driver");
    Connection conn = DriverManager.getConnection(
        "jdbc:h2:" + getServletContext().getRealPath("/") + 
        "/WEB-INF/data/myDB", "sa", "");
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES");
    while (rs.next()) {
    }
    rs.close();
    stmt.close();
    conn.close();
} catch(SQLException e) {
} catch(ClassNotFoundException e) {
} finally {
}
Run Code Online (Sandbox Code Playgroud)

这是在Tomcat8上用H2 1.3.176测试的.它应该适用于H2 1.4并且CIPHER=AES我认为嵌入式数据库已经在war文件中了.

这个想法如下:您需要获取绝对路径,并且该部署路径可能不同,具体取决于您部署war文件的方式.

所以我们需要使用servlet上下文并请求真实路径.为此,我们根据您的需要使用getServletContext().getRealPath("/")和追加/WEB-INF/data/myDB它.

CIPHER=AES因为我从未使用它,所以我没有测试该部件.

更新:

获得对servlet上下文的良好引用是棘手的.可以使用原始请求,获取基础会话,然后转到servlet上下文.

但是,一旦在Tomcat中部署/启动应用程序,就会立即打开嵌入式H2数据库,并在应用程序停止后立即正常关闭.

为了执行该操作,需要使用监听器.这是我建议作为我之前答案的更新.这次使用AES CIPHER完成解决方案,并且应该很容易插入代码.

建议:可以轻松修改监听器java代码以启动H2 tcp服务器,对启用自动混合模式(embedded + tcp)很有用.

在文件web.xml中添加3行:

<listener>
  <listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)

文件MyServletContextListener.java:

package com.mine;

import javax.servlet.*;
import java.sql.*;

public class MyServletContextListener implements ServletContextListener {
  Connection conn;

  public void contextInitialized(ServletContextEvent sce) {

    try {
      Class.forName("org.h2.Driver");
      conn = DriverManager.getConnection( "jdbc:h2:" + sce.getServletContext().getRealPath("/") + "/WEB-INF/data/myDB;CIPHER=AES", "sa", "aespassword dbpassword");
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES");
      while (rs.next()) {
      }
      rs.close();
      stmt.close();
    } catch(SQLException e) {
    } catch(ClassNotFoundException e) {
    } finally {
    }

  }

  public void contextDestroyed(ServletContextEvent sce) {

    try {
      conn.close();
    } catch(SQLException e) {
    } finally {
    }

  }

}
Run Code Online (Sandbox Code Playgroud)