[java] 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]. 아마도 여기에 간단한 것이 빠져 있지만 도움이 될 것입니다.



답변

DB_CLOSE_DELAY=-1

hbm2ddl은 테이블을 생성 한 후 연결을 닫으므로 h2는 삭제합니다.

연결 URL을 다음과 같이 구성한 경우

jdbc:h2:mem:test

마지막 연결이 닫히는 순간 데이터베이스의 내용이 손실됩니다.

콘텐츠를 유지하려면 다음과 같이 URL을 구성해야합니다

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

그렇게하면 h2vm 이 유지되는 동안 내용을 유지합니다 .

콜론 ( ;)이 아니라 세미콜론 ( )을 확인 하십시오 :.

참고 항목 인 – 메모리 데이터베이스 의 섹션 기능 페이지를. 인용 :

기본적으로 데이터베이스에 대한 마지막 연결을 닫으면 데이터베이스가 닫힙니다. 인 메모리 데이터베이스의 경우 이는 내용이 손실되었음을 의미합니다. 데이터베이스를 열어 두려면 ;DB_CLOSE_DELAY=-1데이터베이스 URL에 추가하십시오 . 가상 머신이 활성 상태 인 한 인 메모리 데이터베이스의 컨텐츠를 유지하려면을 사용하십시오 jdbc:h2:mem:test;DB_CLOSE_DELAY=-1.


답변

나는 이것이 당신의 경우가 아니라는 것을 알고 있지만 H2는 대문자로 이름을 가진 테이블을 만든 다음 모든 스크립트 (작성 스크립트 포함)에서 소문자를 사용하더라도 대소 문자를 구분하므로 동일한 문제가 발생했습니다.

;DATABASE_TO_UPPER=false연결 URL 에 추가 하여 해결했습니다 .


답변

말하기 어렵다. 이것을 테스트하는 프로그램을 만들었습니다.

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

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"의 예외 org.h2.jdbc.JdbcSQLException : "PERSON"테이블을 찾을 수 없습니다. SQL 문 :
사람 (ID, 성, 이름)에 삽입 (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 클래스를 찾을 수있는 테이블이 여전히있었습니다.


답변

나는 추가하려고했습니다

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

그러나 그것은 도움이되지 못했습니다. 온 H2 사이트 , 난 정말 어떤 경우에 도움이 될 다음을 발견했다.

기본적으로 데이터베이스에 대한 마지막 연결을 닫으면 데이터베이스가 닫힙니다. 인 메모리 데이터베이스의 경우 이는 내용이 손실되었음을 의미합니다. 데이터베이스를 열어 두려면; DB_CLOSE_DELAY = -1을 데이터베이스 URL에 추가하십시오. 가상 머신이 활성 상태 인 한 인 메모리 데이터베이스의 컨텐츠를 유지하려면 jdbc : h2 : mem : test; DB_CLOSE_DELAY = -1을 사용하십시오.

그러나 내 문제는 스키마 만 기본 스키마와 달라야한다는 것입니다. 그래서 사용의 insted

JDBC URL: jdbc:h2:mem:test

나는 사용해야했다 :

JDBC URL: jdbc:h2:mem:testdb

그런 다음 테이블이 보입니다.


답변

나는 같은 문제가 있었고 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 {
...
}


답변

테이블 메타 데이터를 가져 오려고했지만 다음 오류가 발생했습니다.

사용 :

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 를 지정해야했습니다.