【问题标题】:Can I have H2 autocreate a schema in an in-memory database?我可以让 H2 在内存数据库中自动创建模式吗?
【发布时间】:2011-07-10 16:31:18
【问题描述】:

(我已经看过H2 database In memory - Init schema via Spring/Hibernate的问题;这里不适用。)

我想知道 H2 中是否有允许我在连接到它时自动创建架构的设置。如果有帮助,我只对内存中的情况感兴趣。

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

【问题讨论】:

    标签: java sql database h2


    【解决方案1】:

    是的,H2 支持executing SQL statements when connecting。你可以运行一个脚本,或者只是一个或两个语句:

    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 的模式名称。
    • 请注意,如果您将 H2 与 hibernate 一起使用并希望通过调用 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...
    • @pinkpanther 是的,请参阅stackoverflow.com/questions/4490138/…
    【解决方案2】:

    如果您将 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 中也可以通过这种方式创建模式
    • 非常感谢。我使用此技巧解决了导致我的代码在 4 天内无法工作的问题。
    • 像魅力一样工作
    【解决方案3】:

    Thomas 写的是正确的,除此之外,如果你想初始化多个模式,你可以使用以下。请注意,有一个\\; 分隔两个创建语句。

        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

    【讨论】:

      【解决方案4】:

      “默认情况下,当应用程序调用DriverManager.getConnection(url, ...) 并且URL 中指定的数据库还不存在时,会创建一个新的(空)数据库。”—H2 Database

      附录:@Thomas Mueller 展示了如何Execute SQL on Connection,但我有时只是在代码中创建和填充,如下所示。

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

      【讨论】:

      • 是的,那是 catalogdatabase,而不是其中的架构。例如,您可能会打开到 jdbc:h2:mem:test 的连接,但默认情况下,您会被置于 PUBLIC 模式中,并且不存在其他模式。
      【解决方案5】:

      如果您使用带有application.yml 的Spring Framework,并且无法让测试在INIT 属性上找到SQL 文件,则可以使用classpath: 表示法。

      例如,如果您在src/test/resources 上有一个init.sql SQL 文件,just use

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

      【讨论】:

        【解决方案6】:

        如果您使用的是 spring 和 xml 配置,这里是一个示例:

        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close" depends-on="h2Server">
        <property name="driverClassName" value="org.h2.Driver"/>
        <property name="url"
                  value="jdbc:h2:mem:testdb;INIT=RUNSCRIPT FROM 'classpath:db/create_tables.sql'\;RUNSCRIPT FROM 'classpath:db/insert.sql';TRACE_LEVEL_FILE=4;TRACE_LEVEL_SYSTEM_OUT=3;"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
        

        【讨论】:

          猜你喜欢
          • 2021-10-06
          • 2013-01-02
          • 1970-01-01
          • 2014-10-06
          • 1970-01-01
          • 2015-01-08
          • 2014-05-06
          • 2014-11-25
          • 2020-04-20
          相关资源
          最近更新 更多