我有一个带有网址"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]
。我可能在这里遗漏了一些简单的东西,但任何帮助都会受到赞赏。
答案 0 :(得分:283)
hbm2ddl在创建表后关闭连接,因此h2将其丢弃。
如果您的connection-url配置如下
jdbc:h2:mem:test
在最后一次连接关闭时,数据库的内容将丢失。
如果你想保留你的内容,你必须像这样配置网址
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
如果这样做,只要 vm 存在, h2 就会保留其内容。
答案 1 :(得分:82)
我知道这不是你的情况,但我遇到了同样的问题,因为H2正在创建具有大写名称的表,然后表现区分大小写,即使在所有脚本(包括创建脚本)中我使用小写。
通过将;DATABASE_TO_UPPER=false
添加到连接网址来解决此问题。
答案 2 :(得分: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();
}
}
测试完成,没有失败,也没有意外输出。您正在运行哪个版本的h2?
答案 3 :(得分:6)
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();
}
}
和
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 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类。
答案 4 :(得分:4)
我试图添加
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
然而,这并没有帮助。在H2 site上,我发现了以下内容,在某些情况下确实可以提供帮助。
默认情况下,关闭与数据库的最后一个连接会关闭数据库。对于内存数据库,这意味着内容丢失。要使数据库保持打开状态,请将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
然后表格可见
答案 5 :(得分:1)
我正在尝试获取表元数据,但是出现以下错误:
使用:
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
答案 6 :(得分:1)
我在对Spring引导版本2.2.6的 Spring Data JPA 依赖项添加了依赖关系后,发现它可以正常工作。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
在application.yml中添加H2 DB配置-
spring:
datasource:
driverClassName: org.h2.Driver
initialization-mode: always
username: sa
password: ''
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
h2:
console:
enabled: true
path: /h2
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: none
答案 7 :(得分:1)
遇到了完全相同的问题,尝试了以上所有方法,但没有成功。 错误的相当有趣的原因是 JVM在创建数据库表之前启动太快(使用src.main.resources中的data.sql文件)。因此,在调用“ select * from person”之前,我放置了一个Thread.sleep(1000)计时器等待一秒钟。 现在可以正常工作。
application.properties:
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
data.sql:
create table person
(
id integer not null,
name varchar(255) not null,
location varchar(255),
birth_date timestamp,
primary key(id)
);
insert into person values (
10001, 'Tofu', 'home', sysdate()
);
PersonJdbcDAO.java:
public List<Person> findAllPersons(){
return jdbcTemplate.query("select * from person",
new BeanPropertyRowMapper<Person>(Person.class));
}
主类:
Thread.sleep(1000);
logger.info("All users -> {}", dao.findAllPersons());
答案 8 :(得分:1)
我遇到了同样的问题,并将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 {
...
}
答案 9 :(得分:1)
我来到这个帖子是因为我有同样的错误。
在我的情况下,数据库演变没有被执行,所以表根本就没有。
我的问题是进化脚本的文件夹结构是错误的。
来自:https://www.playframework.com/documentation/2.0/Evolutions
播放使用多个演进脚本跟踪您的数据库演变。这些脚本使用普通的旧SQL编写,应位于应用程序的conf / evolutions / {database name}目录中。如果演进适用于您的默认数据库,则此路径为conf / evolutions / default。
我有一个名为 conf / evolutions.default 的文件夹,由eclipse创建。将文件夹结构更正为 conf / evolutions / default
后,问题就消失了答案 10 :(得分:0)
通过创建新的src / test / resources文件夹+插入application.properties文件(明确指定创建测试数据库)来解决:
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
答案 11 :(得分:0)
打开h2-console时,JDBC URL必须与属性中指定的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
这似乎很明显,但是我花了几个小时才弄清楚这一点。
答案 12 :(得分:0)
<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>
答案 13 :(得分:0)
我已经尝试了上述解决方案,但就控制台的建议而言,在我的情况下添加了属性 DB_CLOSE_ON_EXIT = FALSE ,它解决了该问题。
spring.datasource.url=jdbc:h2:mem:testdb;DATABASE_TO_UPPER=false;DB_CLOSE_ON_EXIT=FALSE
答案 14 :(得分:0)
我尝试添加;DATABASE_TO_UPPER=false
参数,该参数确实可以完成一次测试,但是对我来说,诀窍是;CASE_INSENSITIVE_IDENTIFIERS=TRUE
。
我当时有:jdbc:h2:mem:testdb;CASE_INSENSITIVE_IDENTIFIERS=TRUE
此外,对我来说,问题是当我升级到Spring Boot 2.4.1
时。
答案 15 :(得分:0)
在我的情况下,jpa 测试期间发生了缺失表错误,表是由 schem.sql 文件创建的,在测试 @org.springframework.transaction.annotation.Transactional 后问题得到解决
答案 16 :(得分:0)
适用于 Spring Boot 2.4+ 采用 spring.jpa.defer-datasource-initialization=true 在 application.properties 中
答案 17 :(得分:0)
我参加聚会可能有点晚了,但我遇到了完全相同的错误,我尝试了这里和其他网站上提到的几乎所有解决方案,例如 DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1; DB_CLOSE_ON_EXIT=假;忽略情况=真
但对我来说没有任何效果。 对我有用的是将 data.sql 重命名为 import.sql
我在这里找到的 - https://stackoverflow.com/a/53179547/8219358
或
对于 Spring Boot 2.4+,在 application.properties 中使用 spring.jpa.defer-datasource-initialization=true(此处提到 - https://stackoverflow.com/a/68086707/8219358)
我意识到其他解决方案更合乎逻辑,但没有一个对我有用,而这确实有效。
答案 18 :(得分:-2)
Time.sleep(1000);
这对我有用。只是尝试一下,如果您的PC速度很慢,则可以增加线程的持续时间,以使DB正常工作,并且JVM可以获取我们的表。