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>