URL "jdbc:h2:test"
のH2データベースを持っています。 CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64));
を使用してテーブルを作成します。次に、SELECT * FROM PERSON
を使用して、この(空の)テーブルからすべてを選択します。ここまでは順調ですね。
ただし、URLを"jdbc:h2:mem:test"
に変更すると、データベースがメモリのみにあるという唯一の違いが、org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: SELECT * FROM PERSON [42102-154]
になります。私はおそらくここで簡単なものを見逃していますが、どんな助けもありがたいです。
hbm2ddlは、テーブルの作成後に接続を閉じるため、h2はそれを破棄します。
このように設定された接続URLがある場合
jdbc:h2:mem:test
最後の接続が閉じられると、データベースのコンテンツは失われます。
コンテンツを保持したい場合は、このようにURLを設定する必要があります
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
そうする場合、h2はvmが存続する限りその内容を保持します。
私はこれがあなたのケースではないことを知っていますが、すべてのスクリプト(作成スクリプトを含む)で小文字を使用していても、H2が大文字名でテーブルを作成し、大文字と小文字を区別していたため、同じ問題がありました。
接続URLに;DATABASE_TO_UPPER=false
を追加して解決しました。
わかりにくい。これをテストするプログラムを作成しました:
package com.gigaspaces.compass;
import org.testng.annotations.Test;
import Java.sql.*;
public class H2Test {
@Test
public void testDatabaseNoMem() throws SQLException {
testDatabase("jdbc:h2:test");
}
@Test
public void testDatabaseMem() throws SQLException {
testDatabase("jdbc:h2:mem:test");
}
private void testDatabase(String url) throws SQLException {
Connection connection= DriverManager.getConnection(url);
Statement s=connection.createStatement();
try {
s.execute("DROP TABLE PERSON");
} catch(SQLException sqle) {
System.out.println("Table not found, not dropping");
}
s.execute("CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64))");
PreparedStatement ps=connection.prepareStatement("select * from PERSON");
ResultSet r=ps.executeQuery();
if(r.next()) {
System.out.println("data?");
}
r.close();
ps.close();
s.close();
connection.close();
}
}
テストは完了し、失敗も予期せぬ出力もありませんでした。どのバージョンのh2を実行していますか?
H2インメモリデータベースは、JVM内のメモリにデータを格納します。 JVMが終了すると、このデータは失われます。
あなたがしていることは、以下の2つのJavaクラスに似ていると思います。これらのクラスの1つはテーブルを作成し、他のクラスはテーブルに挿入しようとします。
import Java.sql.*;
public class CreateTable {
public static void main(String[] args) throws Exception {
DriverManager.registerDriver(new org.h2.Driver());
Connection c = DriverManager.getConnection("jdbc:h2:mem:test");
PreparedStatement stmt = c.prepareStatement("CREATE TABLE PERSON (ID INT PRIMARY KEY, FIRSTNAME VARCHAR(64), LASTNAME VARCHAR(64))");
stmt.execute();
stmt.close();
c.close();
}
}
そして
import Java.sql.*;
public class InsertIntoTable {
public static void main(String[] args) throws Exception {
DriverManager.registerDriver(new org.h2.Driver());
Connection c = DriverManager.getConnection("jdbc:h2:mem:test");
PreparedStatement stmt = c.prepareStatement("INSERT INTO PERSON (ID, FIRSTNAME, LASTNAME) VALUES (1, 'John', 'Doe')");
stmt.execute();
stmt.close();
c.close();
}
}
これらのクラスを次々に実行すると、次の出力が得られました。
C:\ Users\Luke\stuff> Java CreateTable C:\ Users\Luke\stuff> Java InsertIntoTable スレッド「main」組織の例外。 h2.jdbc.JdbcSQLException:テーブル「PERSON」が見つかりません。 SQLステートメント: INSERT INTO PERSON(ID、FIRSTNAME、LASTNAME)VALUES(1、 'John'、 'Doe')[42102-154] at org.h2.message.DbException.getJdbcSQLException (DbException.Java:327) at org.h2.message.DbException.get(DbException.Java:167) at org.h2.message.DbException.get(DbException.Java:144 ) ...
最初のJava
プロセスが終了するとすぐに、CreateTable
によって作成されたテーブルは存在しなくなります。したがって、InsertIntoTableクラスが登場すると、挿入するテーブルがなくなります。
接続文字列をjdbc:h2:test
に変更すると、そのようなエラーは発生していません。ファイルtest.h2.db
が現れたことも発見しました。これは、H2がテーブルを配置した場所であり、ディスクに保存されていたため、InsertIntoTableクラスが検索するためにテーブルはまだそこにありました。
私は追加しようとしました
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
しかし、それは助けにはなりませんでした。 H2サイト で、私は以下を見つけました。
デフォルトでは、データベースへの最後の接続を閉じるとデータベースが閉じます。インメモリデータベースの場合、これはコンテンツが失われることを意味します。データベースを開いたままにするには、; DB_CLOSE_DELAY = -1をデータベースURLに追加します。仮想マシンが動作している限り、インメモリデータベースのコンテンツを保持するには、jdbc:h2:mem:test; DB_CLOSE_DELAY = -1を使用します。
ただし、、私の問題は、スキーマだけがデフォルトのものとは異なるはずであるということでした。だから使用する
JDBC URL: jdbc:h2:mem:test
私は使用しなければなりませんでした:
JDBC URL: jdbc:h2:mem:testdb
その後、テーブルが表示されました
同じエラーが発生したため、この投稿に行きました。
私の場合、データベースの進化は実行されなかったため、テーブルはまったくありませんでした。
私の問題は、進化スクリプトのフォルダー構造が間違っていたことです。
from: https://www.playframework.com/documentation/2.0/Evolutions
Playは、いくつかの進化スクリプトを使用してデータベースの進化を追跡します。これらのスクリプトは単純な古いSQLで記述されており、アプリケーションのconf/evolutions/{database name}ディレクトリに配置する必要があります。進化がデフォルトのデータベースに適用される場合、このパスはconf/evolutions/defaultです。
Eclipseによって作成されたconf/evolutions.defaultというフォルダーがありました。フォルダー構造をconf/evolutions/defaultに修正すると、問題はなくなりました
テーブルのメタデータを取得しようとしましたが、次のエラーが発生しました:
を使用して:
String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
DatabaseMetaData metaData = connection.getMetaData();
...
metaData.getColumns(...);
空のResultSetを返しました。
ただし、代わりに次のURLを使用すると、正常に機能しました。
String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false";
指定する必要がありました:DATABASE_TO_UPPER = false
私は同じ問題を抱えていて、application-test.propertiesの構成を次のように変更しました。
#Test Properties
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
そして私の依存関係:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.198</version>
<scope>test</scope>
</dependency>
そして、テストクラスで使用される注釈:
@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("test")
public class CommentServicesIntegrationTests {
...
}
<bean id="benchmarkDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
新しいsrc/test/resourcesフォルダーを作成してapplication.propertiesファイルを挿入し、テストdbaseの作成を明示的に指定することで解決しました。
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create