¿Puedo hacer que H2 cree automáticamente un esquema en una base de datos en memoria?


93

(Ya he visto la base de datos H2 en la memoria: esquema de inicio a través de la pregunta Spring / Hibernate ; no es aplicable aquí).

Me gustaría saber si hay una configuración en H2 que me permita crear automáticamente un esquema al conectarme a él. Si ayuda, solo me interesa el caso en memoria.

H2 admite varios modificadores separados por punto y coma al final de la URL, pero no encontré ninguno para crear automáticamente un esquema. ¿Existe tal característica?

Respuestas:


172

Sí, H2 admite la ejecución de sentencias SQL al conectarse . Puede ejecutar un script o solo una declaración o dos:

String url = "jdbc:h2:mem:test;" + 
             "INIT=CREATE SCHEMA IF NOT EXISTS TEST"
String url = "jdbc:h2:mem:test;" + 
             "INIT=CREATE SCHEMA IF NOT EXISTS TEST\\;" + 
                  "SET SCHEMA TEST";
String url = "jdbc:h2:mem;" + 
             "INIT=RUNSCRIPT FROM '~/create.sql'\\;" + 
                  "RUNSCRIPT FROM '~/populate.sql'";

Tenga en cuenta que la doble barra invertida ( \\) solo es necesaria en Java. Se requiere la barra invertida (s) antes de ;dentro de INIT.


Muchas gracias; No estoy seguro de cómo me perdí eso en la (excelente) documentación.
— Laird Nelson

Gracias, hizo el trabajo ya que estaba usando conjuntos de cambios generados de liquibase que usan el nombre de esquema para xml generado.
— Jaime Hablutzel

2
Tenga en cuenta que si usa H2 con hibernación y desea ejecutar varios scripts llamando a RUNSCRIPT , debe escribir triple barra invertida (\\\). Por ejemplo, debe realizar la configuración <property name="hibernate.connection.url">jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'script1.sql'\\\;RUNSCRIPT FROM script2.sql'</property>en su configuración de hibernación.
— Johnny

@Johnny ¿Estás seguro? Parece que ;no es necesario escapar (hay un sin escapar ;antes de INIT). ¿Podría intentarlo si usar solo una barra invertida funciona? 'script1.sql'\;RUNSCRIPT...
— Thomas Mueller


14

Si está utilizando spring con application.yml, lo siguiente funcionará para usted

spring: datasource: url: jdbc:h2:mem:mydb;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;INIT=CREATE SCHEMA IF NOT EXISTS calendar


También es posible crear un esquema de esta manera en Grails 3
— xtheshadowgod

1
Muchas gracias. Utilicé este consejo para solucionar un problema que provocaba que mi código no funcionara durante 4 días.
— Deepboy

9

Lo que Thomas ha escrito es correcto, además de eso, si desea inicializar múltiples esquemas, puede usar lo siguiente. Tenga en cuenta que hay una \\;separación de las dos declaraciones de creación.

    EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
                    .setType(EmbeddedDatabaseType.H2)
                    .setName("testDb;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=create " +
                            "schema if not exists " +
                            "schema_a\\;create schema if not exists schema_b;" +
                            "DB_CLOSE_DELAY=-1;")
                    .addScript("sql/provPlan/createTable.sql")
                    .addScript("sql/provPlan/insertData.sql")
                    .addScript("sql/provPlan/insertSpecRel.sql")
                    .build();

ref: http://www.h2database.com/html/features.html#execute_sql_on_connection


8

"De forma predeterminada, cuando una aplicación llama DriverManager.getConnection(url, ...)y la base de datos especificada en la URL aún no existe, se crea una nueva base de datos (vacía)". - Base de datos H2 .

Anexo: @Thomas Mueller muestra cómo ejecutar SQL en la conexión , pero a veces solo creo y completo el código, como se sugiere a continuación.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/** @see http://stackoverflow.com/questions/5225700 */
public class H2MemTest {

    public static void main(String[] args) throws Exception {
        Connection conn = DriverManager.getConnection("jdbc:h2:mem:", "sa", "");
        Statement st = conn.createStatement();
        st.execute("create table customer(id integer, name varchar(10))");
        st.execute("insert into customer values (1, 'Thomas')");
        Statement stmt = conn.createStatement();
        ResultSet rset = stmt.executeQuery("select name from customer");
        while (rset.next()) {
            String name = rset.getString(1);
            System.out.println(name);
        }
    }
}

Sí, y ese es el catálogo o la base de datos , no un esquema dentro de él. Por lo tanto, puede abrir una conexión a jdbc: h2: mem: test, por ejemplo, pero de forma predeterminada se le coloca en el esquema PUBLIC y no existe ningún otro esquema.
— Laird Nelson

0

Si está utilizando Spring Framework application.ymly tiene problemas para hacer que la prueba encuentre el archivo SQL en la INITpropiedad, puede usar la classpath:notación.

Por ejemplo, si tiene un init.sqlarchivo SQL en el src/test/resources, simplemente use :

url=jdbc:h2:~/test;INIT=RUNSCRIPT FROM 'classpath:init.sql';DB_CLOSE_DELAY=-1;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.