Java H2内存数据库。找不到表

Java H2内存数据库。找不到表,java,database,h2,Java,Database,H2,我有一个H2数据库,URL“jdbc:H2:test”。我使用createtableperson(ID INT主键,FIRSTNAME VARCHAR(64),LASTNAME VARCHAR(64))创建一个表。然后,我使用select*from PERSON从这个(空)表中选择所有内容。到目前为止,一切顺利 但是,如果我将URL更改为“jdbc:h2:mem:test”,唯一的区别是数据库现在只在内存中,这给了我一个org.h2.jdbc.jdbcsql异常:未找到表“PERSON”;SQL

我有一个H2数据库,URL
“jdbc:H2:test”
。我使用
createtableperson(ID INT主键,FIRSTNAME VARCHAR(64),LASTNAME VARCHAR(64))创建一个表。然后,我使用
select*from PERSON
从这个(空)表中选择所有内容。到目前为止,一切顺利


但是,如果我将URL更改为
“jdbc:h2:mem:test”
,唯一的区别是数据库现在只在内存中,这给了我一个
org.h2.jdbc.jdbcsql异常:未找到表“PERSON”;SQL语句:从PERSON[42102-154]中选择*。我可能在这里遗漏了一些简单的东西,但任何帮助都将不胜感激。

很难说。我创建了一个程序来测试这一点:

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退出时,这些数据将丢失

我怀疑您所做的与下面的两个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();
    }
}

当我一个接一个地运行这些类时,我得到了以下输出:

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) ... C:\Users\Luke\stuff>JavaCreateTable C:\Users\Luke\stuff>java插入表 线程“main”org.h2.jdbc.JdbcSQLException中的异常:未找到表“PERSON”;SQL语句: 在PERSON(ID、FIRSTNAME、LASTNAME)中插入值(1,'John','Doe')[42102-154] 位于org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 位于org.h2.message.DbException.get(DbException.java:167) 位于org.h2.message.DbException.get(DbException.java:144) ... 一旦第一个
java
进程退出,由
CreateTable
创建的表就不再存在。因此,当InsertIntoTable类出现时,没有可供插入的表

当我将连接字符串更改为
jdbc:h2:test
时,我发现没有这样的错误。我还发现出现了一个文件
test.h2.db
。这是H2放置表的地方,因为它存储在磁盘上,所以该表仍然在那里,InsertIntoTable类可以找到它。

DB\u CLOSE\u DELAY=-1
hbm2ddl在创建表后关闭连接,因此h2将丢弃它

如果您的连接url配置如下

jdbc:h2:mem:test
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
数据库的内容在最后一个连接关闭时丢失

如果你想保留你的内容,你必须像这样配置url

jdbc:h2:mem:test
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
如果这样做,h2将在vm存在期间保留其内容

请注意分号(
)而不是冒号(

请参见“功能”页面的部分。引述:

默认情况下,关闭与数据库的最后一个连接将关闭数据库。对于内存中的数据库,这意味着内容丢失。要保持数据库打开,请添加
;数据库URL的DB_CLOSE_DELAY=-1
。要在虚拟机处于活动状态时保持内存中数据库的内容,请使用
jdbc:h2:mem:test;DB\u CLOSE\u DELAY=-1


我知道这不是您的情况,但我也遇到了同样的问题,因为H2创建表时使用大写名称,然后表现为区分大小写,即使在所有脚本(包括创建脚本)中,我都使用小写


通过添加
解决;连接URL的数据库\u TO \u UPPER=false

我来这篇文章是因为我犯了同样的错误

在我的例子中,数据库进化没有被执行,所以表根本不存在

我的问题是进化脚本的文件夹结构是错误的

发件人:

Play使用几个演进脚本跟踪数据库演进。这些脚本是用普通的旧SQL编写的,应该位于应用程序的conf/evolutions/{database name}目录中。如果演化应用于默认数据库,则此路径为conf/evolutions/default

我有一个由eclipse创建的名为conf/evolutions.default的文件夹。在我将文件夹结构更正为我尝试添加的conf/evolutions/default后,问题消失了

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
然而,这没有帮助。在这方面,我发现了以下几点,这在某些情况下确实会有所帮助

默认情况下,关闭与数据库的最后一个连接将关闭数据库。对于内存中的数据库,这意味着内容丢失。要保持数据库打开,请添加;数据库URL的DB_CLOSE_DELAY=-1。要在虚拟机处于活动状态时保持内存中数据库的内容,请使用jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

然而,我的问题是模式应该与默认模式不同。所以不用

JDBC URL: jdbc:h2:mem:test
我必须使用:

JDBC URL: jdbc:h2:mem:testdb
然后这些表就可以看到了


<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文件夹+insert application.properties文件来解决,并明确指定要创建测试数据库:

spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create

我遇到了相同的问题,并将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>

我试图获取表元数据,但出现以下错误:

使用:

String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";

DatabaseMetaData metaData = connection.getMetaData();
...
metaData.getColumns(...);
返回一个空的结果集

但使用以下URL,它工作正常:

String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false";

需要指定:DATABASE\u to\u UPPER=false

打开h2控制台时,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
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=


这似乎很明显,但我花了数小时来解决这个问题。

遇到了完全相同的问题,尝试了上述所有方法,但没有成功。 这个错误相当有趣的原因是在创建DB表之前,JVM启动得太快了(使用src.main.resources中的data.sql文件)。所以我设置了一个Thread.sleep(1000)计时器,在调用“select*from person”之前只需等待一秒钟。 完美地工作
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()
);
    public List<Person> findAllPersons(){
    return jdbcTemplate.query("select * from person", 
        new BeanPropertyRowMapper<Person>(Person.class));
}
Thread.sleep(1000);
logger.info("All users -> {}", dao.findAllPersons());
    <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>
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
 spring.datasource.url=jdbc:h2:mem:testdb;DATABASE_TO_UPPER=false;DB_CLOSE_ON_EXIT=FALSE