java - how - Base de datos en memoria H2. Tabla no encontrada
spring boot h2 sql file (7)
Tengo una base de datos H2 con la URL "jdbc:h2:test"
. Creo una tabla usando CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64));
. Luego selecciono todo de esta tabla (vacía) usando SELECT * FROM PERSON
. Hasta aquí todo bien.
Sin embargo, si cambio la URL a "jdbc:h2:mem:test"
, la única diferencia es que la base de datos ahora está solo en la memoria, esto me da una org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: SELECT * FROM PERSON [42102-154]
org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: SELECT * FROM PERSON [42102-154]
. Probablemente me esté perdiendo algo simple aquí, pero cualquier ayuda sería apreciada.
Difícil de decir. Creé un programa para probar esto:
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();
}
}
La prueba se ejecutó hasta su finalización, sin fallas y sin resultados inesperados. ¿Qué versión de h2 estás ejecutando?
He intentado agregar
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Sin embargo, eso no ayudó. En el sitio H2 , he encontrado lo siguiente, que de hecho podría ayudar en algunos casos.
Por defecto, cerrar la última conexión a una base de datos cierra la base de datos. Para una base de datos en memoria, esto significa que el contenido se pierde. Para mantener la base de datos abierta, agregue; DB_CLOSE_DELAY = -1 a la URL de la base de datos. Para mantener el contenido de una base de datos en memoria mientras la máquina virtual esté activa, use jdbc: h2: mem: test; DB_CLOSE_DELAY = -1.
Sin embargo , mi problema era que solo se suponía que el esquema era diferente al predeterminado. Insiste en usar
JDBC URL: jdbc:h2:mem:test
Tuve que usar:
JDBC URL: jdbc:h2:mem:testdb
Entonces las tablas eran visibles
La base de datos en memoria H2 almacena los datos en la memoria dentro de la JVM. Cuando sale la JVM, esta información se pierde.
Sospecho que lo que estás haciendo es similar a las dos clases de Java a continuación. Una de estas clases crea una tabla y la otra intenta insertarla:
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();
}
}
y
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();
}
}
Cuando ejecuté estas clases una después de la otra, obtuve el siguiente resultado:
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) ...
Tan pronto como java
el primer proceso de java
, la tabla creada por CreateTable
ya no existe. Entonces, cuando aparece la clase InsertIntoTable, no hay una tabla para insertar.
Cuando cambié las cadenas de conexión a jdbc:h2:test
, encontré que no había tal error. También encontré que había aparecido un archivo test.h2.db
Aquí fue donde H2 colocó la tabla, y como se había almacenado en el disco, la tabla todavía estaba allí para que la clase InsertIntoTable la encontrara.
Llegué a esta publicación porque tuve el mismo error.
En mi caso, las evoluciones de la base de datos no se habían ejecutado, por lo que la tabla no estaba allí en absoluto.
Mi problema era que la estructura de la carpeta para los scripts de evolución era incorrecta.
desde: https://www.playframework.com/documentation/2.0/Evolutions
Play rastrea las evoluciones de su base de datos usando varias secuencias de comandos de evolución. Estos scripts están escritos en SQL antiguo y deben ubicarse en el directorio conf / evolutions / {database name} de su aplicación. Si las evoluciones se aplican a su base de datos predeterminada, esta ruta es conf / evolutions / default.
Tenía una carpeta llamada conf / evolutions.default creada por eclipse. El problema desapareció después de que corregí la estructura de la carpeta a conf / evolutions / default
Sé que este no era su caso, pero tuve el mismo problema porque H2 creaba las tablas con nombres MAYÚSCULAS y luego se comportaba con mayúsculas y minúsculas, aunque en todos los scripts (incluidos los de creación) usaba minúsculas.
Resuelto agregando ;DATABASE_TO_UPPER=false
a la URL de conexión.
hbm2ddl cierra la conexión después de crear la tabla, por lo que h2 la descarta.
Si tiene su url de conexión configurada así
jdbc:h2:mem:test
el contenido de la base de datos se pierde en el momento en que se cierra la última conexión.
Si desea conservar su contenido, debe configurar la URL como esta
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Si lo haces, h2 mantendrá su contenido mientras viva la vm .
<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>