Bellek içi bir veritabanında H2'nin otomatik olarak şema oluşturmasını sağlayabilir miyim?


97

(Halihazırda H2 veritabanını Bellekte gördüm - Şemayı İlkbahar / Hazırda Beklet sorusuyla başlat ; burada geçerli değil.)

H2'de, ona bağlandıktan sonra otomatik olarak bir şema oluşturmama izin verecek bir ayar olup olmadığını bilmek istiyorum. Yardımı dokunursa, sadece bellek içi durumla ilgileniyorum.

H2, URL'nin sonunda çeşitli noktalı virgülle ayrılmış değiştiricileri destekliyor, ancak otomatik olarak bir şema oluşturmak için bir tane bulamadım. Böyle bir özellik var mı?

Yanıtlar:


177

Evet, H2 bağlanırken SQL ifadelerinin yürütülmesini destekler . Bir komut dosyası veya yalnızca bir veya iki ifade çalıştırabilirsiniz:

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

Çift ters eğik çizginin ( \\) yalnızca Java'da gerekli olduğunu lütfen unutmayın . Önce ters eğik çizgi (ler) ;içinde INITgereklidir.


Çok teşekkür ederim; (mükemmel) belgelerde bunu nasıl kaçırdığımdan emin değilim.
Laird Nelson

Teşekkürler, oluşturulan xml için şema adını kullanan likibase'den oluşturulan değişiklik setlerini kullandığım için çalışmayı başardı.
Jaime Hablutzel

2
H2'yi hazırda bekletme ile kullanıyorsanız ve RUNSCRIPT'i çağırarak birden çok komut dosyası çalıştırmak istiyorsanız , üçlü ters eğik çizgi (\\\) yazmanız gerektiğini unutmayın. Örneğin, <property name="hibernate.connection.url">jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'script1.sql'\\\;RUNSCRIPT FROM script2.sql'</property>hazırda bekletme yapılandırmanızda ayarlamalısınız .
Johnny

@Johnny Emin misin? Görünüşe göre kaçılmasına ;gerek yok ( ;önünden bir kaçış var INIT). Yalnızca bir ters eğik çizgi kullanmanın işe yarayıp yaramadığını deneyebilir misiniz? 'script1.sql'\;RUNSCRIPT...
Thomas Mueller


18

Spring'i application.yml ile kullanıyorsanız, aşağıdakiler sizin için çalışacaktır

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


Grails 3
Rhineb

1
Çok teşekkür ederim. Bu ipucunu, kodumun 4 gün boyunca çalışmamasına neden olan bir sorunu düzeltmek için kullandım.
Deepboy

9

Thomas'ın yazdıkları doğrudur, buna ek olarak, birden fazla şemayı başlatmak istiyorsanız, aşağıdakileri kullanabilirsiniz. \\;İki create ifadesinin birbirinden ayrıldığını unutmayı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

"Varsayılan olarak, bir uygulama aradığında DriverManager.getConnection(url, ...)ve URL'de belirtilen veritabanı henüz mevcut olmadığında, yeni (boş) bir veritabanı oluşturulur." - H2 Veritabanı .

Ek: @Thomas Mueller, Bağlantıda SQL'in nasıl yürütüleceğini gösteriyor , ancak bazen aşağıda önerildiği gibi kodu oluşturup dolduruyorum .

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

Evet ve bu katalog veya veritabanıdır , içindeki bir şema değil. Örneğin, jdbc: h2: mem: test'e bir bağlantı açabilirsiniz, ancak varsayılan olarak PUBLIC şemasına yerleştirilirsiniz ve başka şema yoktur.
Laird Nelson

1

Spring Framework ile birlikte kullanıyorsanız application.ymlve testin INITözellikteki SQL dosyasını bulmasını sağlamakta sorun yaşıyorsanız , classpath:gösterimi kullanabilirsiniz .

Örneğin, üzerinde bir init.sqlSQL dosyanız varsa src/test/resources, şunu kullanın :

url=jdbc:h2:~/test;INIT=RUNSCRIPT FROM 'classpath:init.sql';DB_CLOSE_DELAY=-1;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.