H2 база данных в памяти. Таблица не найдена
у меня есть база данных H2 с URL "jdbc:h2:test"
. Я создаю таблицу, используя CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64));
. Затем я выбираю все из этой (пустой) таблицы, используя SELECT * FROM PERSON
. Пока все идет хорошо.
однако, если я изменю URL на "jdbc:h2:mem:test"
, единственная разница в том, что база данных теперь находится только в памяти, это дает мне org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: SELECT * FROM PERSON [42102-154]
. Я, вероятно, пропустил что-то простое здесь, но любая помощь была бы оценена.
7 ответов
hbm2ddl закрывает соединение после создания таблицы, поэтому h2 отбрасывает его.
Если у вас есть подключение-url настроен следующим образом
jdbc:h2:mem:test
содержимое базы данных теряется в момент закрытия последнего соединения.
Если вы хотите сохранить свой контент, вы должны настроить url-адрес следующим образом
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Если это так,h2 будет держать его содержание до тех пор, как vm жизнь.
Я знаю, что это не ваш случай, но у меня была та же проблема, потому что H2 создавал таблицы с именами в верхнем регистре, а затем вел себя с учетом регистра, хотя во всех сценариях (в том числе в создании) я использовал нижний регистр.
решена путем добавления ;DATABASE_TO_UPPER=false
к URL-адресу подключения.
трудно сказать. Я создал программу для проверки этого:
package com.gigaspaces.compass;
import org.testng.annotations.Test;
import java.sql.*;
public class H2Test {
@Test
public void testDatabaseNoMem() throws SQLException {
testDatabase("jdbc:h2:test");
}
@Test
public void testDatabaseMem() throws SQLException {
testDatabase("jdbc:h2:mem:test");
}
private void testDatabase(String url) throws SQLException {
Connection connection= DriverManager.getConnection(url);
Statement s=connection.createStatement();
try {
s.execute("DROP TABLE PERSON");
} catch(SQLException sqle) {
System.out.println("Table not found, not dropping");
}
s.execute("CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64))");
PreparedStatement ps=connection.prepareStatement("select * from PERSON");
ResultSet r=ps.executeQuery();
if(r.next()) {
System.out.println("data?");
}
r.close();
ps.close();
s.close();
connection.close();
}
}
тест завершен, без сбоев и неожиданного вывода. Какую версию h2 вы используете?
база данных в памяти H2 хранит данные в памяти внутри JVM. Когда JVM выходит, эти данные теряются.
Я подозреваю, что то, что вы делаете, похоже на два класса Java ниже. Один из этих классов создает таблицу, а другой пытается вставить в нее:
import java.sql.*;
public class CreateTable {
public static void main(String[] args) throws Exception {
DriverManager.registerDriver(new org.h2.Driver());
Connection c = DriverManager.getConnection("jdbc:h2:mem:test");
PreparedStatement stmt = c.prepareStatement("CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64))");
stmt.execute();
stmt.close();
c.close();
}
}
и
import java.sql.*;
public class InsertIntoTable {
public static void main(String[] args) throws Exception {
DriverManager.registerDriver(new org.h2.Driver());
Connection c = DriverManager.getConnection("jdbc:h2:mem:test");
PreparedStatement stmt = c.prepareStatement("INSERT INTO PERSON (ID, FIRSTNAME, LASTNAME) VALUES (1, 'John', 'Doe')");
stmt.execute();
stmt.close();
c.close();
}
}
когда я запускал эти классы один за другим, я получил следующий вывод:
C:\Users\Luke\stuff>java CreateTable C:\Users\Luke\stuff>java InsertIntoTable Exception in thread "main" org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: INSERT INTO PERSON (ID, FIRSTNAME, LASTNAME) VALUES (1, 'John', 'Doe') [42102-154] at org.h2.message.DbException.getJdbcSQLException(DbException.java:327) at org.h2.message.DbException.get(DbException.java:167) at org.h2.message.DbException.get(DbException.java:144) ...
как только первый java
процесс завершается, таблица, созданная CreateTable
больше не существует. Таким образом, когда появляется класс InsertIntoTable, для него нет таблицы для вставки.
когда я изменил строку подключения jdbc:h2:test
, я обнаружил, что такой ошибки не было. Я также обнаружил, что файл было. Это было место, куда H2 поместил таблицу, и так как она была сохранена на диске, таблица все еще была там для InsertIntoTable класса, чтобы найти.
Я пытался добавить
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
однако это не помогло. На сайт H2, я обнаружил следующее, что действительно могло бы помочь в некоторых случаях.
по умолчанию закрытие последнего соединения с базой данных закрывает базу данных. Для базы данных в памяти, это означает, что содержимое теряется. Чтобы сохранить базу данных открытой, добавьте; DB_CLOSE_DELAY=-1 в URL базы данных. Чтобы сохранить содержимое базы данных в памяти до тех пор, пока виртуальная машина живой, используйте jdbc:h2:mem: test;DB_CLOSE_DELAY=-1.
, моя проблема заключалась в том, что только схема должна отличаться от схемы по умолчанию. Так что используйте
JDBC URL: jdbc:h2:mem:test
мне пришлось использовать:
JDBC URL: jdbc:h2:mem:testdb
тогда таблицы были видны
Я пришел на этот пост, потому что у меня была такая же ошибка.
в моем случае эволюция базы данных не была выполнена, поэтому таблицы вообще не было.
моя проблема заключалась в том, что структура папок сценариев эволюции был неправ.
from:https://www.playframework.com/documentation/2.0/Evolutions
Play отслеживает эволюцию базы данных, используя несколько сценариев эволюции. Эти сценарии написаны простым языком старый SQL и должен быть расположен в каталоге conf/evolutions/{database name} вашего приложения. Если эволюция применяется к базе данных по умолчанию, этот путь-conf/evolutions / default.
У меня была папка под названием conf / evolutions.по умолчанию создано eclipse. Проблема исчезла после того, как я исправил структуру папок на conf/evolutions / default
<bean id="benchmarkDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>