Как показать содержимое локальной базы данных h2 (веб-консоль)?
Недавно я присоединился к новой команде, и здесь парни используют h2 для обслуживания заглушки.
Мне было интересно, могу ли я показать содержимое этой базы данных с помощью веб-интерфейса. На работе это доступно, перейдя в localhost:5080
У меня есть проект, в котором я использую базу данных h2, но не могу увидеть веб-консоль h2, когда нажимаю localhost:5080
Я пробовал также 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. пожалуйста помоги.
PS
Я вижу упоминания о h2 только в .m2
папка
PS2
Я заметил, что веб-консоль доступна http://localhost:8082/
Если заменить URL в конфигурации с:
<property name="url" value="jdbc:h2:tcp://localhost/~/test;MODE=PostgreSQL" />
Но это работает, если я уже запускаю h2 (в .m2
папка найти h2
файл фляги и двойной щелчок)
Если 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 запускался, если он не запускался при запуске приложения.
PS3
Я попытался написать следующий код:
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
PS4
Этот код работает:
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();
}
}
но мне нужно вызывать его только тогда, когда активен конкретный пружинный профиль (теперь он работает всегда)
3 ответа
Давайте разделим вопрос на две части.
В зависимости от того, как вы указали соединение с H2, вы получите разные режимы работы.
Режимы: встроенный, в памяти, сервер.
jdbc:h2:~/test
дает вам экземпляр H2 во встроенном режиме. Встроенный режим имеет ограничение на доступ только через тот же загрузчик классов и ту же JVM ( доказательство)
jdbc:h2:mem:test
дает вам экземпляр H2 в памяти. Это также не доступно из внешнего мира.
jdbc:h2:tcp://localhost/test
запустит сервер H2, и он будет доступен вне режима сервера JVM, но с одним ограничением - сервер должен быть запущен до установления соединения.
Последнее ограничение вызывает ваши Connection refused: connect: localhost"
исключение.
Подводя итог все:
- Запустите сервер H2, прежде чем запускать приложение
- использование
jdbc:h2:tcp://localhost/test
как строка подключения - ....
- счастливого кодирования:)
Обновить
Просто заметил, что вы хотите запустить сервер в процессе запуска приложения.
Вы можете сделать это несколькими способами, в зависимости от того, как вы запускаете приложение:
- Если вы используете maven / gradle, вам будет проще добавить какой-нибудь профиль / задачу, чтобы она выполнялась до того, как приложение действительно запустится.
- Если вам нужно все настроить в Java, я предлагаю вам взглянуть на этот вопрос
Обновление 2
Если подключение к локальной базе данных требуется только для целей разработки / отладки, я бы все настроил, используя профиль maven. Ответы на этот вопрос решат это.
Если вам нужен доступ к базе данных H2 в производственном режиме (я вряд ли смогу представить какой-либо вариант использования для этого), лучше сделать это весной. Главным образом потому, что настройка контейнера приложения / среды, вероятно, будет отличаться в рабочей среде (по сравнению со средой разработки).
Чтобы решить вопрос о том, запускать сервер вне контекста Spring или нет - все зависит от требований. Стоит отметить, что сервер должен быть запущен до запуска источника данных (в противном случае контекст весны не будет загружен).
Обновление 3
К сожалению, я не могу дать вам рабочее решение, но согласно JavaDocs есть разница между TCP-сервером и веб-сервером. Присмотритесь к JavaDoc класса H2 Server.
Я думаю, вы должны использовать Server.createWebServer()
способ создания сервера (разница между TCP-сервером и веб-сервером заключается в том, что
Еще один замечательный класс, который вы могли бы использовать org.h2.tools.Console
( JavaDoc здесь) Просто запустите основной метод консоли, и я думаю, что это должно решить все.
Вы должны иметь возможность использовать варианты в памяти или на основе файлов, а затем в своем приложении запустить сервер TCP TCP отдельно, например, с помощью bean-компонента Spring (обратите внимание на полупсевдокод и пример порта):
@Component
class Bootstrap {
@PostConstruct
public void startH2TcpServer() {
Server.createTcpServer("-tcpPort", "9123", "-tcpDaemon").start();
}
}
Как насчет изменения URL JDBC в конфигурации, чтобы включить
AUTO_SERVER=TRUE
начать h2 автоматически.
Несколько процессов могут обращаться к одной и той же базе данных без необходимости запуска сервера вручную. Для этого добавьте;AUTO_SERVER=TRUE к URL базы данных. Вы можете использовать один и тот же URL базы данных независимо от того, открыта ли база данных или нет. Эта функция не работает с базами данных в памяти.
Используйте один и тот же URL для всех подключений к этой базе данных. Внутренне, при использовании этого режима, первое соединение с базой данных выполняется во встроенном режиме, и дополнительно сервер запускается изнутри (как поток демона). Если база данных уже открыта в другом процессе, режим сервера используется автоматически.