Jor*_*orn 170 java database h2
我有一个带有URL的H2数据库"jdbc:h2:test"
.我使用创建一个表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]
.我可能在这里遗漏了一些简单的东西,但任何帮助都会受到赞赏.
rei*_*901 304
hbm2ddl在创建表后关闭连接,所以h2丢弃它.
如果您的connection-url配置如下
jdbc:h2:mem:test
Run Code Online (Sandbox Code Playgroud)
在最后一次连接关闭时,数据库的内容将丢失.
如果你想保留你的内容,你必须像这样配置网址
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Run Code Online (Sandbox Code Playgroud)
如果这样做,只要vm存在,h2就会保留其内容.
Cri*_*bie 90
我知道这不是你的情况,但我遇到了同样的问题,因为H2正在创建具有大写名称的表,然后表现区分大小写,即使在所有脚本(包括创建脚本)中我使用小写.
通过添加;DATABASE_TO_UPPER=false
到连接URL 解决.
Out*_*ONE 11
一个原因可能是jpa尝试在创建表结构之前插入数据,为了解决这个问题,在application.properties中插入这一行:
spring.jpa.defer-datasource-initialization=true
Run Code Online (Sandbox Code Playgroud)
Jos*_*ger 10
很难说.我创建了一个程序来测试这个:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
测试完成,没有失败,也没有意外输出.您运行的是哪个版本的h2?
小智 9
For Spring Boot 2.4+ use spring.jpa.defer-datasource-initialization=true in application.properties
我试图添加
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Run Code Online (Sandbox Code Playgroud)
然而,这没有帮助。在H2 站点上,我发现了以下内容,在某些情况下确实可以提供帮助。
默认情况下,关闭与数据库的最后一个连接将关闭该数据库。对于内存数据库,这意味着内容丢失。要保持数据库打开,请将 ;DB_CLOSE_DELAY=-1 添加到数据库 URL。要在虚拟机处于活动状态时保留内存数据库的内容,请使用 jdbc:h2:mem:test;DB_CLOSE_DELAY=-1。
但是,我的问题是模式应该与默认模式不同。所以开始使用
JDBC URL: jdbc:h2:mem:test
Run Code Online (Sandbox Code Playgroud)
我不得不使用:
JDBC URL: jdbc:h2:mem:testdb
Run Code Online (Sandbox Code Playgroud)
然后桌子是可见的
打开 h2-console 时,JDBC URL 必须与属性中指定的匹配:
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.h2.console.enabled=true
Run Code Online (Sandbox Code Playgroud)
这似乎很明显,但我花了几个小时弄清楚这一点..
H2内存数据库将数据存储在JVM内的内存中.当JVM退出时,此数据将丢失.
我怀疑你所做的与下面的两个Java类相似.其中一个类创建一个表,另一个尝试插入其中:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
和
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();
}
}
Run Code Online (Sandbox Code Playgroud)
当我一个接一个地运行这些类时,我得到以下输出:
C:\Users\Luke\stuff>java CreateTable C:\Users\Luke\stuff>java InsertIntoTable Exception in thread "main" org.h2.jdbc.JdbcSQLException: Table "PERSON" not found; SQL statement: 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类查找.
小智 6
我试图获取表元数据,但出现以下错误:
使用:
String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
DatabaseMetaData metaData = connection.getMetaData();
...
metaData.getColumns(...);
Run Code Online (Sandbox Code Playgroud)
返回一个空的结果集。
但使用以下 URL 则可以正常工作:
String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false";
Run Code Online (Sandbox Code Playgroud)
需要指定:DATABASE_TO_UPPER=false
小智 5
通过创建一个新的 src/test/resources 文件夹 + 插入 application.properties 文件来解决,明确指定创建一个测试数据库:
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题,并将 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
Run Code Online (Sandbox Code Playgroud)
还有我的依赖:
<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>
Run Code Online (Sandbox Code Playgroud)
以及测试类上使用的注释:
@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("test")
public class CommentServicesIntegrationTests {
...
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
131182 次 |
最近记录: |