如何显示本地 h2 数据库(Web 控制台)的内容?

How to show content of local h2 database(web console)?

最近我加入了一个新团队,这里的人使用 h2 作为存根服务。

我想知道是否可以使用 Web 界面显示此数据库的内容。在工作时,前往 localhost:5080

即可获得

我有一个使用 h2 数据库的项目,但是当我点击 localhost:5080

时我看不到 h2 web 控制台

我也试过 localhost:8082 - 它也不起作用。

我的项目配置(成功运行):

     <bean id="wrappedDataSource" class="net.bull.javamelody.SpringDataSourceFactoryBean">
        <property name="targetName" value="dataSource" />
     </bean>

     <bean id="wrappedDataSource" class="net.bull.javamelody.SpringDataSourceFactoryBean">
            <property name="targetName" value="dataSource" />
        </bean>

        <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
            <property name="driverClassName" value="org.h2.Driver" />
            <property name="url" value="jdbc:h2:~/test;MODE=PostgreSQL" />
            <property name="username" value="sa" />
            <property name="password" value="" />
        </bean>

        <bean id="sessionFactory"
              class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="wrappedDataSource"/>
            <property name="configLocation">
                <value>classpath:hibernate-test.cfg.xml</value>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.connection.charSet">UTF-8</prop>
                    <prop key="hibernate.format_sql">true</prop>
                    <prop key="hbm2ddl.auto">create-drop</prop>
                </props>
            </property>
        </bean>

        <context:property-placeholder location="classpath:jdbc.properties"/>

我不知道如何访问 h2 web 控制台。请帮忙

P.S.

我只在 .m2 文件夹中看到提到 h2

P.S.2

我注意到,如果将配置中的 url 替换为:

,则 http://localhost:8082/ 可以使用 Web 控制台
<property name="url" value="jdbc:h2:tcp://localhost/~/test;MODE=PostgreSQL" />

但是 如果我已经启动 h2(在 .m2 文件夹中找到 h2 jar 文件并双击)它就可以工作

如果在我启动应用程序时 h2 未启动 - 我看到以下错误:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
    ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dbInitializer': Invocation of init method failed; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
    ...
Caused by: org.hibernate.exception.GenericJDBCException: Could not open connection
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
    ...
Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Соединение разорвано: "java.net.ConnectException: Connection refused: connect: localhost"
Connection is broken: "java.net.ConnectException: Connection refused: connect: localhost" [90067-182])
    at org.apache.commons.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:1549)
    ...
Caused by: org.h2.jdbc.JdbcSQLException: Соединение разорвано: "java.net.ConnectException: Connection refused: connect: localhost"
Connection is broken: "java.net.ConnectException: Connection refused: connect: localhost" [90067-182]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
    ...
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    ...

如果我启动我的应用程序时它没有启动,我想实现 h2 启动。

P.S.3

我尝试编写了以下代码:

Server server = null;
try {
    server = Server.createTcpServer("-tcpAllowOthers").start();
    Class.forName("org.h2.Driver");
    Connection conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test;MODE=PostgreSQL", "sa", "");
 } catch (Exception e) {
    LOG.error("Error while initialize", e);
 }

我执行它并尝试在我的浏览器中输入 localhost:9092

此时正在下载文件。内部文件包含以下内容:

Version mismatch, driver version is “0” but server version is “15”

我的 h2 版本 1.4.182

P.S.4

此代码有效:

public class H2Starter extends ContextLoaderListener {
    private static final Logger LOG = LoggerFactory.getLogger(H2Starter.class);

    @Override
    public void contextInitialized(ServletContextEvent event) {

        startH2();
        super.contextInitialized(event);
    }

    private static void startH2() {

        try {
            Server.createTcpServer("-tcpAllowOthers").start();
            Class.forName("org.h2.Driver");
            DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test;MODE=PostgreSQL;AUTO_SERVER=TRUE", "sa", "");

            Server.createWebServer().start();
        } catch (Exception e) {
            LOG.error("cannot start H2 [{}]", e);
        }
    }

    public static void main(String[] args) {
        startH2();
    }
}

但我只需要在具体 spring 配置文件处于活动状态时调用它(现在它始终有效)

让我们把问题分成两部分。

根据您指定与 H2 的连接方式,您将获得不同的操作模式。

模式有:嵌入式、内存中、服务器。

jdbc:h2:~/testembedded mode 中给你一个 H2 实例。 嵌入式模式有一个限制,只能通过相同的 class 加载程序和相同的 JVM (proof)

访问

jdbc:h2:mem:test 为您提供一个内存中的 H2 实例。这也是无法从外部世界访问

jdbc:h2:tcp://localhost/test 将启动 H2 服务器,并且可以从 JVM 外部 访问 server mode 但有一个限制 - 服务器需要先启动已建立连接。

最后一个限制导致了您的 Connection refused: connect: localhost" 异常。

总结一下:

  • 在启动应用程序之前启动H2服务器
  • 使用jdbc:h2:tcp://localhost/test作为连接字符串
  • .....
  • 快乐编码:)

更新

刚刚注意到您要在启动应用程序的过程中启动服务器。

您可以通过多种方式执行此操作,具体取决于您如何启动应用程序:

  • 如果您使用的是 maven / gradle,您可以更轻松地添加一些配置文件/任务,以便它在应用程序实际启动之前执行。
  • 如果您必须在 java 中设置所有内容,我建议您查看此

更新 2

如果仅出于开发/调试目的需要连接到本地数据库,我将使用 maven 配置文件设置所有内容。 this question 的回答将解决这个问题。

如果您需要在生产中访问 H2 数据库(我很难想象有任何用例),最好在 spring 中执行此操作。主要是因为应用程序容器/环境设置在生产环境中可能有所不同(与开发环境相比)。

解决关于是否在 Spring 上下文之外启动服务器的问题 - 这完全取决于要求。 您应该注意的一件事是服务器应该在 数据源启动之前启动(否则 spring 上下文将不会加载)

更新 3

很遗憾,我无法为您提供可行的解决方案,但根据 JavaDocs,TCP 服务器和 Web 服务器之间存在差异。 仔细看看 JavaDoc of H2 Server class.

我猜你应该使用 Server.createWebServer() 方法来创建服务器(TCP 服务器和 Web 服务器的区别在于

另一个很棒的 class 你可以使用 org.h2.tools.Console (JavaDoc here) 只是 运行 Console 的主要方法,我想应该可以解决所有问题。

您应该能够使用内存中或基于文件的变体,然后在您的应用程序中单独启动 H2 TCP 服务器,例如使用 Spring bean(注意半伪代码和示例端口):

@Component
class Bootstrap {
    @PostConstruct
    public void startH2TcpServer() {
         Server.createTcpServer("-tcpPort", "9123", "-tcpDaemon").start();
    }
}

http://www.h2database.com/html/tutorial.html#using_server

如何更改配置中的 jdbc url 以包含

AUTO_SERVER=TRUE 

自动启动 h2。

Auto mixed mode

Multiple processes can access the same database without having to start the server manually. To do that, append ;AUTO_SERVER=TRUE to the database URL. You can use the same database URL independent of whether the database is already open or not. This feature doesn't work with in-memory databases.

Use the same URL for all connections to this database. Internally, when using this mode, the first connection to the database is made in embedded mode, and additionally a server is started internally (as a daemon thread). If the database is already open in another process, the server mode is used automatically.