使用 DBCP 池在服务器模式下远程连接到 H2 数据库

Posted

技术标签:

【中文标题】使用 DBCP 池在服务器模式下远程连接到 H2 数据库【英文标题】:Remote connection to a H2 database in server mode with DBCP pooling 【发布时间】:2014-07-02 09:57:22 【问题描述】:

我正在尝试创建一个嵌入式 H2 服务器,我也可以远程访问它并使用 Tomcat DBCP 池。

这是我生成数据源的代码:

@Produces @ApplicationScoped
public DataSource getDataSource() throws NamingException, SQLException 
    dataSource = new BasicDataSource();
    dataSource.setDriverClassName("org.h2.jdbcx.JdbcDataSource");
    dataSource.setUrl("jdbc:h2:/tmp/myapp");
    dataSource.setUsername("sa");
    dataSource.setPassword("");
    dataSource.setMaxActive(100);
    dataSource.setMaxIdle(30);
    dataSource.setMaxWait(10000);
    // start the pool
    Connection connection = dataSource.getConnection();
    // start the server
    server = Server.createTcpServer("-tcpAllowOthers").start();
    connection.close();
    return dataSource;

当我尝试使用 URL“jdbc:h2:tcp://192.168.2.58//tmp/myapp”(192.168.2.58 是远程服务器的 IP)这是我得到的错误:

Database may be already in use: "/tmp/myapp.mv.db". Possible solutions: close all other connection(s); use the server mode [90020-179] 90020/90020

有人有解决办法吗?

【问题讨论】:

【参考方案1】:

下面是最终起作用的代码:

@ApplicationScoped
public class DataSourceProducer 

    private JdbcDataSource dataSource;
    private Server server;

    @Produces @ApplicationScoped
    public DataSource getDataSource() throws NamingException, SQLException 
        dataSource = new JdbcDataSource();
        dataSource.setUrl("jdbc:h2:/tmp/myapp");
        dataSource.setUser("sa");
        dataSource.setPassword("");
        // start the server
        server = Server.createTcpServer("-tcpAllowOthers").start();
        return dataSource;
    

    public void disposeDataSource(@Disposes DataSource dataSource) throws SQLException 
        server.stop();
    

然后我可以使用 URL jdbc:h2:tcp://<remote ip>//tmp/myapp 访问它(至少我通过 SSH 隧道 9020 端口使其工作并使用 jdbc:h2:tcp://localhost//tmp/myapp 访问它)

【讨论】:

【参考方案2】:

检查H2 Multiple connections。您需要客户端/服务器模式才能多次打开数据库。默认情况下,嵌入式数据库不能多次打开。您需要使用“自动混合模式”功能:

Mixed Mode for H2 database

因此,如果您按以下方式修改 jdbc url,它应该可以工作:

jdbc:h2:/tmp/myapp;AUTO_SERVER=TRUE

【讨论】:

混合模式的问题是不能远程访问,我想从另一台电脑访问。此外,当我创建 TCP 服务器时,我已经将它用作客户端/服务器模式......但也许这是我第一次使用的嵌入式连接,它锁定了数据库...... 我更仔细地阅读了您的代码。您创建一个到嵌入式数据库的连接(因为 jdbc url),然后创建一个服务器。当您远程调用服务器时,第一个连接会阻止它访问数据库。尝试先启动服务器,然后使用 jdbc url 创建连接:“jdbc:h2:tcp://127.0.0.1//tmp/myapp”,然后尝试远程连接 我认为这可行。但我不会再在我的 Web 应用程序中处于“嵌入模式”=> 它的优化程度会有所降低...... 好吧,您不能拥有嵌入式数据库并且能够多次打开它。唯一的选择是拥有嵌入式数据库并提供远程查询服务。

以上是关于使用 DBCP 池在服务器模式下远程连接到 H2 数据库的主要内容,如果未能解决你的问题,请参考以下文章

无法在自动混合模式下连接到 H2 数据库

混合模式的 H2 数据库远程连接 (Auto_server=true)

H2 客户端无法连接到服务器

在服务器模式下使用 H2 可能的最大连接数

H2数据库HTTPS连接

无法使用桥接网络模式从 docker 容器连接到远程 SQL 服务器