Чи можу я H2 автоматично створити схему в базі даних в пам'яті?


93

(Я вже бачив базу даних H2 в пам’яті - схему ініціювання через запитання Spring / Hibernate ; вона тут не застосовується.)

Я хотів би знати, чи є параметр у H2, який дозволить мені автоматично створювати схему при підключенні до неї. Якщо це допомагає, мене цікавить лише справа в пам'яті.

H2 підтримує різні модифікатори, розділені крапкою з комою в кінці URL-адреси, але я не знайшов такого для автоматичного створення схеми. Чи є така особливість?

Відповіді:


171

Так, H2 підтримує виконання операторів SQL під час підключення . Ви можете запустити сценарій, або просто заяву або два:

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

Зверніть увагу, подвійна коса коса риса ( \\) потрібна лише на Java. Потрібна зворотна коса риса (риски) перед ;в межах INIT.


Велике спасибі; не впевнений, як я це пропустив у (чудовій) документації.
Лейрд Нельсон,

Дякую, це зробило роботу, оскільки я використовував згенеровані набори змін з liquibase, які використовують ім’я схеми для згенерованого xml.
Jaime Hablutzel

2
Зверніть увагу, що якщо ви використовуєте H2 з режимом глибокого сну і хочете запускати кілька сценаріїв, викликаючи RUNSCRIPT , вам слід ввести потрійну зворотну скісну риску (\\\). Наприклад, вам слід встановити налаштування <property name="hibernate.connection.url">jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'script1.sql'\\\;RUNSCRIPT FROM script2.sql'</property>у режимі глибокого сну.
Джонні,

@Johnny Ви впевнені? Схоже , що ;не потрібно екранувати (є неекранований ;перед INIT). Не могли б ви спробувати, якщо працює лише одна зворотна коса риса? 'script1.sql'\;RUNSCRIPT...
Thomas Mueller


14

Якщо ви використовуєте spring з application.yml, вам підійде наступне

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


Також можна створити схему таким чином у
Граалях

1
Велике спасибі. Я використав цю підказку, щоб виправити проблему, через яку мій код не працював протягом 4 днів.
Deepboy

9

Томас написав правильно, на додаток до цього, якщо ви хочете ініціалізувати кілька схем, ви можете використовувати наступне. Зауважте, що \\;два оператори створення розділяють.

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

посилання: http://www.h2database.com/html/features.html#execute_sql_on_connection


8

"За замовчуванням, коли програма телефонує, DriverManager.getConnection(url, ...)а база даних, вказана в URL-адресі, ще не існує, створюється нова (порожня) база даних." - База даних H2 .

Додаток: @Thomas Mueller показує, як виконувати SQL при підключенні , але я іноді просто створюю та заповнюю код, як пропонується нижче.

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

Так, і це каталог або база даних , а не схема всередині них. Отже, ви можете відкрити підключення до jdbc: h2: mem: test, наприклад, але за замовчуванням вас поміщають у СХЕМУ PUBLIC, і жодної іншої схеми не існує.
Laird Nelson,

0

Якщо ви використовуєте Spring Framework application.ymlі маєте проблеми з тестом, щоб знайти файл SQL у INITвластивості, ви можете використовувати classpath:позначення.

Наприклад, якщо у вас є init.sqlфайл SQL src/test/resources, просто використовуйте :

url=jdbc:h2:~/test;INIT=RUNSCRIPT FROM 'classpath:init.sql';DB_CLOSE_DELAY=-1;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.