Dapatkah saya membuat H2 membuat skema secara otomatis dalam database dalam memori?

95

(Saya telah melihat database H2 Dalam memori - Skema Init melalui pertanyaan Spring / Hibernate ; ini tidak berlaku di sini.)

Saya ingin tahu apakah ada pengaturan di H2 yang memungkinkan saya membuat skema secara otomatis saat menyambungkannya. Jika itu membantu, saya hanya tertarik pada kasus dalam memori.

H2 mendukung berbagai pengubah yang dipisahkan titik koma di akhir URL, tetapi saya tidak menemukannya untuk membuat skema secara otomatis. Apakah ada fitur seperti itu?

Laird Nelson
sumber

Jawaban:

176

Ya, H2 mendukung eksekusi pernyataan SQL saat menghubungkan . Anda dapat menjalankan skrip, atau hanya satu atau dua pernyataan:

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'";

Harap dicatat bahwa garis miring terbalik ganda ( \\) hanya diperlukan di dalam Java. Garis miring terbalik (es) sebelum ;dalam INITdiperlukan.

Thomas Mueller
sumber
Terima kasih banyak; tidak yakin bagaimana saya melewatkannya di dokumentasi (sangat baik).
Laird Nelson
Terima kasih, itu berhasil karena saya menggunakan perubahan yang dihasilkan dari liquibase yang menggunakan nama skema untuk xml yang dihasilkan.
Jaime Hablutzel
2
Perhatikan bahwa jika Anda menggunakan H2 dengan hibernate dan ingin menjalankan banyak skrip dengan memanggil RUNSCRIPT , Anda harus mengetikkan garis miring terbalik tiga kali (\\\). Misalnya, Anda harus mengatur <property name="hibernate.connection.url">jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'script1.sql'\\\;RUNSCRIPT FROM script2.sql'</property>di konfigurasi hibernasi Anda.
Johnny
@ Johnny Apakah Anda yakin? Sepertinya ;tidak perlu di-escape (ada yang tidak di-escape ;sebelum INIT). Bisakah Anda mencoba jika hanya menggunakan satu garis miring terbalik yang berfungsi? 'script1.sql'\;RUNSCRIPT...
Thomas Mueller
1
@pinkpanther ya, lihat stackoverflow.com/questions/4490138/…
Thomas Mueller
17

Jika Anda menggunakan spring dengan application.yml, berikut ini akan bekerja untuk Anda

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

Marquis Blount
sumber
Anda juga dapat membuat skema dengan cara ini di Grails 3
xtheshadowgod
1
Terima kasih banyak. Saya menggunakan tip ini untuk memperbaiki masalah yang menyebabkan kode saya tidak berfungsi selama 4 hari.
Deepboy
9

Apa yang Thomas telah tulis benar, selain itu, jika Anda ingin menginisialisasi beberapa skema, Anda dapat menggunakan yang berikut ini. Perhatikan ada yang \\;memisahkan dua pernyataan buat.

    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

Zeus
sumber
8

"Secara default, saat aplikasi memanggil DriverManager.getConnection(url, ...)dan database yang ditentukan dalam URL belum ada, database baru (kosong) dibuat." - Database H2 .

Tambahan: @Thomas Mueller menunjukkan cara Menjalankan SQL pada Koneksi , tetapi terkadang saya hanya membuat dan mengisi kode, seperti yang disarankan di bawah ini.

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);
        }
    }
}
tempat sampah
sumber
Ya, dan itu adalah katalog atau database , bukan skema di dalamnya. Jadi, Anda dapat membuka koneksi ke jdbc: h2: mem: test, misalnya, tetapi secara default Anda ditempatkan di skema PUBLIK, dan tidak ada skema lain.
Laird Nelson
1

Jika Anda menggunakan Spring Framework dengan application.ymldan mengalami kesulitan untuk membuat pengujian menemukan file SQL pada INITproperti, Anda dapat menggunakan classpath:notasi.

Misalnya, jika Anda memiliki init.sqlfile SQL di src/test/resources, gunakan saja :

url=jdbc:h2:~/test;INIT=RUNSCRIPT FROM 'classpath:init.sql';DB_CLOSE_DELAY=-1;
Dherik
sumber