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

Jdbc 在WEB-INF目录中嵌入H2数据库,jdbc,h2,web-inf,Jdbc,H2,Web Inf,我有一个嵌入式H2数据库,我想放在WEB应用程序的WEB-INF目录中 在JDBCURL中引用这个的正确方法是什么 理想情况下,我想要一个既适用于战争又适用于扩大战争(如果可能)的解决方案 谢谢你的帮助 仅供参考,我尝试了以下方法: jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES 但这导致: org.h2.jdbc.JdbcSQLException: A file path that is implicitly relative to the current wor

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

在JDBCURL中引用这个的正确方法是什么

理想情况下,我想要一个既适用于战争又适用于扩大战争(如果可能)的解决方案

谢谢你的帮助

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

jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES
但这导致:

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]
将此更改为: jdbc:h2:./WEB-INF/data/myDB;密码=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]

我成功地使嵌入式解决方案在没有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 {
}
这是在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密码,它应该很容易插入到您的代码

建议:可以轻松修改侦听器java代码以启动H2 tcp服务器,这对于启用自动混合模式(嵌入式+tcp)非常有用

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


根据需要支持的应用程序服务器,在将文件放入webinf时应小心。Websphere在这方面非常挑剔。您是向数据库写入还是只读?最好允许将数据库存储在单独的目录中,并允许以只读方式配置路径,并且只能在Tomcat上部署,最好是WAR格式。不允许在程序文件中写入,请尝试其他路径。我知道我不允许在程序文件中写入。WEB-INF目录也不在Tomcat的bin目录下。我要指出的错误是,相对路径没有达到预期的效果。如果示例符合实际情况,则不会有任何影响;-)@道格:最后,我没有使用servlet进入tcp模式。我想无论war扩展到何处,使用嵌入式模式都会获得更好的性能。@Doug您测试过我建议的修复程序吗?@Doug请确保将此代码放入扩展HttpServlet的类中,否则
getServletContext()
将不可用。由于我没有您的代码的完整视图,您的里程可能会有所不同…@Doug我修复了如何在不使用请求的情况下获取servlet上下文,而是使用侦听器。抱歉,我只是回到这个:-)。我通过将数据库放入内存暂时解决了这个问题,但我将切换到上下文侦听器选项。这肯定是我要寻找的更多,但是我在网上找到的上下文侦听器示例仍然没有处理WEB-INF数据库。感谢您花时间整理了一个很好的答案!
<listener>
  <listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
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 {
    }

  }

}