it-swarm.com.de

H2-In-Memory-Datenbank. Tabelle nicht gefunden

Ich habe eine H2-Datenbank mit der URL "jdbc:h2:test". Ich erstelle mit CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64)); eine Tabelle. Ich wähle dann alles aus dieser (leeren) Tabelle mit SELECT * FROM PERSON aus. So weit, ist es gut.

Wenn ich jedoch die URL in "jdbc:h2:mem:test" ändere, besteht der einzige Unterschied darin, dass sich die Datenbank nur noch im Speicher befindet. Dies gibt mir einen org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: SELECT * FROM PERSON [42102-154]. Ich vermisse hier wahrscheinlich etwas einfaches, aber jede Hilfe wäre dankbar.

151
Jorn

hbm2ddl schließt die Verbindung, nachdem die Tabelle erstellt wurde. h2 verwirft sie also.

Wenn Sie Ihre Verbindungs-URL so konfiguriert haben

jdbc:h2:mem:test

der Inhalt der Datenbank geht in dem Moment verloren, in dem die letzte Verbindung geschlossen wurde.

Wenn Sie Ihren Inhalt behalten möchten, müssen Sie die URL so konfigurieren

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

In diesem Fall behält h2 seinen Inhalt, solange die vm lebt. 

272
reini2901

Ich weiß, dass dies nicht Ihr Fall war, aber ich hatte das gleiche Problem, weil H2 die Tabellen mit UPPERCASE-Namen erstellte und dabei die Groß- und Kleinschreibung berücksichtigte, obwohl ich in allen Skripts (einschließlich der Erstellung) Kleinbuchstaben verwendet habe. 

Gelöst durch Hinzufügen von ;DATABASE_TO_UPPER=false zur Verbindungs-URL. 

77
Cristian Vrabie

Schwer zu erzählen. Ich habe ein Programm erstellt, um dies zu testen: 

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();
}
}

Der Test wurde vollständig ausgeführt, ohne Fehler und keine unerwartete Ausgabe. Welche Version von H2 laufen Sie?

10
Joseph Ottinger

Die H2-In-Memory-Datenbank speichert Daten in der JVM. Wenn die JVM beendet wird, gehen diese Daten verloren. 

Ich vermute, dass Sie ähnlich wie die beiden folgenden Java-Klassen arbeiten. Eine dieser Klassen erstellt eine Tabelle und die andere versucht, sie einzufügen:

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();
    }
}

und

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();
    }
}

Als ich diese Klassen nacheinander durchführte, erhielt ich die folgende Ausgabe:

 C:\Users\Luke\stuff> Java CreateTable 

 C:\Users\Luke\stuff> Java InsertIntoTable 
 Ausnahme im Thread "main" org.h2.jdbc.JdbcSQLException: Table " PERSON "nicht gefunden; SQL-Anweisung: 
 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) 
 ...

Sobald der erste Java-Prozess beendet ist, ist die von CreateTable erstellte Tabelle nicht mehr vorhanden. Wenn also die InsertIntoTable-Klasse kommt, gibt es keine Tabelle, in die sie eingefügt werden kann.

Als ich die Verbindungszeichenfolgen in jdbc:h2:test änderte, stellte ich fest, dass kein solcher Fehler aufgetreten ist. Ich fand auch, dass eine Datei test.h2.db erschienen ist. Hier hatte H2 die Tabelle abgelegt, und da sie auf der Festplatte gespeichert war, war die Tabelle immer noch für die InsertIntoTable-Klasse zu finden.

6
Luke Woodward

Ich habe versucht hinzuzufügen

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

Das hat aber nicht geholfen. Auf der H2-Site habe ich Folgendes gefunden, was in manchen Fällen tatsächlich helfen könnte.

Durch das Schließen der letzten Verbindung zu einer Datenbank wird die Datenbank standardmäßig geschlossen. Bei einer In-Memory-Datenbank bedeutet dies, dass der Inhalt verloren geht. Um die Datenbank offen zu halten, fügen Sie der Datenbank-URL DB_CLOSE_DELAY = -1 hinzu. Verwenden Sie jdbc: h2: mem: test; DB_CLOSE_DELAY = -1, um den Inhalt einer In-Memory-Datenbank beizubehalten, solange die virtuelle Maschine aktiv ist.

Allerdings, mein Problem war, dass nur das Schema anders sein sollte als das Standardschema. Also zu verwenden 

JDBC URL: jdbc:h2:mem:test

Ich musste verwenden:

JDBC URL: jdbc:h2:mem:testdb

Dann waren die Tische sichtbar

3
DevDio

Ich bin zu diesem Beitrag gekommen, weil ich den gleichen Fehler hatte.

In meinem Fall wurden die Datenbankentwicklungen nicht ausgeführt, sodass die Tabelle überhaupt nicht vorhanden war.

Mein Problem war, dass die Ordnerstruktur für die Evolutionsskripte falsch war.

von: https://www.playframework.com/documentation/2.0/Evolutions

Play verfolgt Ihre Datenbankentwicklungen mit mehreren Entwicklungsskripten. Diese Skripts sind in einfachem alten SQL geschrieben und sollten sich im Verzeichnis conf/evolutions/{Datenbankname} Ihrer Anwendung befinden. Wenn die Weiterentwicklungen auf Ihre Standarddatenbank zutreffen, lautet dieser Pfad conf/evolutions/default.

Ich hatte einen Ordner namens conf/evolutions.default, der von Eclipse erstellt wurde. Das Problem verschwand, nachdem ich die Ordnerstruktur auf conf/evolutions/default korrigiert hatte.

1
Oscar Fraxedas

Ich habe versucht, Tabellen-Metadaten abzurufen, hatte jedoch den folgenden Fehler:

Verwenden von:

String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";

DatabaseMetaData metaData = connection.getMetaData();
...
metaData.getColumns(...);

hat ein leeres ResultSet zurückgegeben.

Die Verwendung der folgenden URL funktionierte jedoch ordnungsgemäß:

String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false";

Es musste Folgendes angegeben werden: DATABASE_TO_UPPER = false

Ich hatte das gleiche Problem und änderte meine Konfiguration in application-test.properties folgendermaßen:

#Test Properties
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop

Und meine Abhängigkeiten:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.198</version>
        <scope>test</scope>
    </dependency>

Und die Anmerkungen für die Testklasse:

@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("test")
public class CommentServicesIntegrationTests {
...
}
1
Georgi Peev
<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>
0
Alex R

Beim Öffnen der h2-Konsole muss die JDBC-URL mit der in den Eigenschaften angegebenen übereinstimmen:

spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb

spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true

spring.h2.console.enabled=true

enter image description here

Was offensichtlich erscheint, aber ich habe Stunden damit verbracht, das herauszufinden.

0
nagy.zsolt.hun

Gelöst durch Erstellen eines neuen Ordners src/test/resources + insert application.properties, wobei explizit angegeben wird, dass eine Testdatenbank erstellt wird:

spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
0
N.MATHIEU