我可以让H2在内存数据库中自动创建架构吗?


93

(我已经看过H2数据库在内存中-通过Spring / Hibernate问题的初始化架构;在这里不适用。)

我想知道H2中是否有设置,可以让我在连接到它时自动创建一个模式。如果有帮助,我只对内存中的情况感兴趣。

H2在URL的末尾支持各种用分号分隔的修饰符,但是我找不到用于自动创建模式的修饰符。有这样的功能吗?

Answers:


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中需要双反斜杠()。前的反斜杠(ES);INIT是必需的。


非常感谢你; 不知道我怎么在(优秀)文档中错过了这一点。
尼尔森·尼尔森,

谢谢您,它的工作非常顺利,因为我正在使用来自liquibase的生成变更集,该变更集使用生成的xml的架构名称。
Jaime Hablutzel

2
请注意,如果将H2与hibernate一起使用,并且想通过调用RUNSCRIPT来运行多个脚本,则应键入三反斜杠(\\\)。例如,您应该<property name="hibernate.connection.url">jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'script1.sql'\\\;RUNSCRIPT FROM script2.sql'</property>在休眠配置中进行设置。
约翰尼

@约翰尼你确定吗?看起来;不需要转义(;之前有一个未转义的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


也可以在Grails 3
xtheshadowgod

1
非常感谢你。我使用此技巧来解决导致我的代码在4天内无法正常工作的问题。
Deepboy

9

除此之外,Thomas编写的内容是正确的,如果您要初始化多个模式,则可以使用以下内容。请注意\\;,两个create语句是分开的。

    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显示了如何在Connection执行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模式中,并且不存在其他任何模式。
尼尔森·尼尔森,

0

如果您将Spring Framework与配合使用application.yml,并且无法使测试在该INIT属性上找到SQL文件,则可以使用classpath:表示法。

举例来说,如果你有一个init.sql对SQL文件src/test/resources只需使用

url=jdbc:h2:~/test;INIT=RUNSCRIPT FROM 'classpath:init.sql';DB_CLOSE_DELAY=-1;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.